SQL Server เปลี่ยนโครงสร้าง XML เมื่อแทรก


15

ฉันกำลังแทรกข้อมูล XML บางอย่างไปยังคอลัมน์ XML ใน SQL server แต่หลังจากที่แทรกข้อมูลแล้วมันก็ถูกเปลี่ยนแปลงโดยเซิร์ฟเวอร์ sql นี่คือข้อมูลที่ฉันใส่

              <xsl:value-of select="name/n/given" />
            <xsl:text> </xsl:text>
          <xsl:value-of select="name/n/family" />

เมื่อฉันอ่านมันกลับมาดูเหมือนว่านี้

              <xsl:value-of select="name/n/given" />
          <xsl:text />
          <xsl:value-of select="name/n/family" />

ใส่ใจกับบรรทัดที่สอง นี่เป็นปัญหาเนื่องจากจะเปลี่ยนวิธีที่เอาต์พุตการแปลง XSLT จะเป็น ตัวอย่างแรกจะสร้างช่องว่างระหว่างชื่อที่ให้และชื่อสกุลในขณะที่สองจะไม่สร้างช่องว่างใด ๆ ดังนั้นมันจะเป็นเหมือน JohnJohnsen ในขณะที่คนแรกจะเป็นเหมือน John Johnsen

มีวิธีแก้ปัญหานี้ไหม?


มันเป็นปัญหาเพราะสิ่งนี้จะเปลี่ยนวิธีการส่งออกการแปลง XSLT บรรทัดแรกจะสร้างช่องว่างระหว่างชื่อที่กำหนดและนามสกุลในขณะที่บรรทัดที่สองจะไม่สร้างช่องว่างใด ๆ ระหว่างนั้นจึงจะเป็นเหมือน JohnJohnsen ในขณะที่คนแรกจะเป็นเหมือน John John
Mr Zach

hmhm พื้นที่ที่เหมาะสมมันคือ "" แต่ไม่ได้เป็นเพียงพื้นที่เหมือนในความคิดเห็นนี้ (คุณไม่สามารถดูได้)
a_vlad

1
บางทีคุณอาจใช้อักขระควบคุมที่ไม่มีอยู่ในข้อมูล (เช่น_หรือ~) จากนั้นแทนที่ด้วยช่องว่าง ณ เวลานำเสนอ
Aaron Bertrand

คำตอบ:


25

คุณสามารถใช้xml:space = "preserve"กับโหนดที่คุณต้องการรักษาพื้นที่ การใช้ xml: space เป็นเพียงสัญญาณบ่งบอกถึงเจตนาเท่านั้น แต่ SQL Server ใจดีกับเราที่นี่

สำหรับหนึ่งโหนด

declare @X xml =
'<root>
  <element xml:space = "preserve"> </element>
  <element> </element>
</root>'

select @X;

ผลลัพธ์:

<root>
  <element xml:space="preserve"> </element>
  <element />
</root>

เอกสารทั้งหมด:

declare @X xml =
'<root xml:space = "preserve">
  <element> </element>
  <element> </element>
</root>'

select @X;

ผลลัพธ์:

<root xml:space="preserve">
  <element> </element>
  <element> </element>
</root>

ตัวเลือกสำหรับเอกสารทั้งหมดก็คือการใช้แปลงที่มีสไตล์ 1

รักษาพื้นที่สีขาวที่ไม่มีนัยสำคัญ การตั้งค่าสไตล์นี้ตั้งค่าการจัดการ xml: space ที่เป็นค่าเริ่มต้นเพื่อให้ตรงกับลักษณะการทำงานของ xml: space = "แปรรูป"

declare @X xml = convert(xml, 
'<root>
  <element> </element>
  <element> </element>
</root>', 1)

select @X;

น่าสนใจว่านี่เป็นสิ่งจำเป็น ไม่ควรใช้ SQL Server ในการตัดสินใจว่าช่องว่างใดที่ "ไม่สำคัญ" และตัดออกโดยไม่ต้องแก้ไขเอกสาร!
การแข่งขัน Lightness กับโมนิก้า

3
@LightnessRacesinOrbit ฉันค่อนข้างพอใจกับการใช้งานโดย SQL Server การจัดรูปแบบ (ช่องว่าง) ใน XML จะไม่ถือว่ามีความสำคัญจนกว่าคุณจะระบุว่าเป็น ลองดูตัวอย่างนี้เพื่อดูจำนวนโหนดที่อยู่ในเอกสารและขนาดของพื้นที่จัดเก็บ ..
Mikael Eriksson

3
ฉันคิดว่ามันเป็นการละเมิดข้อมูลจำเพาะเพราะที่นี่ข้อมูลได้รับการยอมรับเป็น XML และเก็บไว้เป็น XML โดยไม่มีการจัดการหรือการแปลงหรือรูปแบบอื่นของ shenanigans XML-layer รูปแบบอื่นนอกเหนือจากการจัดเก็บเอกสาร (อย่างเห็นได้ชัด) ดังนั้นพฤติกรรมควร อยู่ใน "โปรเซสเซอร์" มากกว่า "แอปพลิเคชัน" ดังนั้นจึงต้องไม่ตัดช่องว่างออก
การแข่งขัน Lightness กับโมนิก้า

9

หน้านี้ของเอกสาร SQL Server บอกว่า

ข้อมูลถูกเก็บไว้ในการเป็นตัวแทนภายในที่ ... อาจไม่เหมือนสำเนาของข้อความ XML เนื่องจากข้อมูลต่อไปนี้จะไม่ถูกเก็บไว้: ช่องว่างสีขาวที่ไม่มีนัยสำคัญลำดับของคุณลักษณะคำนำหน้าเนมสเปซและการประกาศ XML

สำหรับตัวอย่างของคุณฉันคิดว่ามันถือว่าพื้นที่สีขาวของแท็กตรงกลางไม่สำคัญและมีอิสระในการปรับโครงสร้างการแสดงแทน ฉันไม่คิดว่าจะมีการแก้ไขสำหรับสิ่งนี้ มันเป็นเพียงวิธีที่ SQL Server ใช้ชนิดข้อมูล XML

การหางานทำได้โดยการใช้ที่ยึดแทนการใช้พื้นที่สีขาว @Aaron พูด ผู้บริโภคจะต้องจำไว้ว่าให้ใส่และถอดโทเค็นเหล่านี้ออก หรือกำหนดคอลัมน์เป็น nvarchar แทน XML สิ่งนี้จะรักษาพื้นที่สีขาวทั้งหมดและการจัดรูปแบบอื่น ๆ อย่างแน่นอน ตัวอย่างรวดเร็ว:

create table x(i nvarchar(99), j xml);
insert x values ('<a> </a>', '<a> </a>');  -- note the space
select * from x

i           j
----------  -------
<a> </a>    <a />  

คอลัมน์ nvarchar สงวนรูปแบบอินพุตคอลัมน์ XML ไม่

คุณจะสูญเสียความสามารถในการใช้ XPATH ในแบบสอบถาม SQL หาก XML มีการฉีกเป็นชิ้นเล็กชิ้นน้อยในแอปพลิเคชัน ยิ่งไปกว่านั้นสตริงอักขระอาจถูกบีบอัดการประหยัดพื้นที่ใน DB หากนี่เป็นสิ่งสำคัญสำหรับคุณ


คุณอาจยังคงใช้ XPATH ในการสืบค้นกับเวอร์ชัน XML แม้ว่าคุณจะปล่อยให้ฟอร์แมตใหม่ตราบใดที่คุณไม่ต้องพึ่งการกดปุ่ม (หรือพลาด) สำหรับพื้นที่ที่ไม่มีนัยสำคัญ
Aaron Bertrand

0

คุณสามารถห่อพื้นที่ภายในCDATAเมื่อจัดเก็บข้อมูล:

<xsl:text><![CDATA[ ]]></xsl:text>

ปรากฏว่าเซิร์ฟเวอร์ SQL แล้วทำให้พื้นที่ภายใน แต่เอาที่ไม่จำเป็นมาร์กอัปตัวเองเมื่อได้รับกลับผลการใช้CDATA SELECTโชคดีที่พื้นที่ถูกเก็บไว้เมื่อนำผลลัพธ์ของ a SELECT:

DECLARE @X XML = '<text><![CDATA[ ]]></text>'
DECLARE @Y XML

SET @Y = (SELECT @X)

SELECT @Y

ผลลัพธ์จะเป็น:

<text> </text>

ลองใช้ CDATA ด้วย แต่มันถูกลบออกไปด้วย
นายซัค

@MrZach CDATA เองถูกลบ แต่พื้นที่ยังคงอยู่ (ทดลองใช้กับ SQL Express 2016)
Bruno

แปลกนี่คือพื้นที่ถูกลบออก คิดยังแสดง 2016 หรือ 2017
นาย Zach
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.