เชื่อมค่าทั้งหมดขององค์ประกอบ XML เดียวกันโดยใช้ XPath / XQuery


14

ฉันมีค่า XML ดังนี้:

<R>
  <I>A</I>
  <I>B</I>
  <I>C</I>
  ...
</R>

ฉันต้องการที่จะเชื่อมทุกค่าและพวกเขากลับเป็นสตริงเดียว:IABC...

ตอนนี้ฉันรู้แล้วว่าฉันสามารถทำลาย XML, รวมผลลัพธ์กลับเป็น XML แบบไม่มีโหนดและนำ.values('text()[1]', ...)ไปใช้กับผลลัพธ์:

SELECT
  (
    SELECT
      n.n.value('text()[1]', 'varchar(50)') AS [text()]
    FROM
      @MyXml.nodes('/R/I') AS n (n)
    FOR XML
      PATH (''),
      TYPE
  ).value('text()[1]', 'varchar(50)')
;

อย่างไรก็ตามฉันต้องการทำทุกอย่างที่ใช้วิธี XPath / XQuery เท่านั้นสิ่งนี้:

SELECT @MyXml. ? ( ? );

มีวิธีดังกล่าวหรือไม่?

เหตุผลที่ฉันกำลังมองหาวิธีแก้ปัญหาในทิศทางนี้เป็นเพราะ XML จริงของฉันมีองค์ประกอบอื่น ๆ เช่น:

<R>
  <I>A</I>
  <I>B</I>
  <I>C</I>
  ...
  <J>X</J>
  <J>Y</J>
  <J>Z</J>
  ...
</R>

และฉันต้องการที่จะสามารถดึงIค่าทั้งสองเป็นสตริงเดี่ยวและJค่าเป็นสตริงเดียวโดยไม่ต้องใช้สคริปต์ที่ไม่สะดวกสำหรับแต่ละรายการ

คำตอบ:


11

สิ่งนี้อาจใช้ได้กับคุณ:

select @MyXml.value('/R[1]', 'varchar(50)')

มันรับtext()องค์ประกอบทั้งหมดจากครั้งแรกRและด้านล่าง

ถ้าคุณต้องการทุกสิ่งที่text()คุณทำได้

select @MyXml.value('.', 'varchar(50)')

หากคุณต้องการค่าสำหรับIและJแยกกันให้ทำเช่นนี้แทน

select @MyXml.query('/R/I/text()').value('.', 'varchar(50)'),
       @MyXml.query('/R/J/text()').value('.', 'varchar(50)')

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

7

ขึ้นอยู่กับโครงสร้าง XML ที่แท้จริงของคุณคุณสามารถลองใช้การวนซ้ำดังนี้:

DECLARE @xml XML

SELECT @xml = '<R>
  <I>A</I>
  <I>B</I>
  <I>C</I>
  <J>X</J>
  <J>Y</J>
  <J>Z</J>
</R>'

SELECT 
    Tbl.Col.query('for $i in I return $i').value('.', 'nvarchar(max)'),
    Tbl.Col.query('for $i in J return $i').value('.', 'nvarchar(max)')
FROM @xml.nodes('R') Tbl(Col);

ซึ่งแสดงผลลัพธ์นี้:

(No column name) | (No column name) 
---------------  | --------------- 
ABC              | XYZ 

ดูซอนี้


1
นี่เป็นสิ่งที่ดีจริงๆ ฉันสามารถปรับให้รวมตัวคั่นได้ทุกเมื่อที่ต้องการ และมันก็ไม่มากเกินไปที่จะถูกใช้อย่างที่มันเป็นในกรณีที่ฉันต้องการแยกสตริงทั้งที่มีและไม่มีตัวคั่นในลักษณะที่เหมือนกัน
Andriy M

0

หากองค์ประกอบและคุณค่าของคุณสั้นและชัดเจนจริง ๆ งานนี้:

declare @s varchar(99) = '<R><I>A</I><I>B</I><I>C</I></R>';

select
    @s,
    REPLACE(TRANSLATE ( @s, '<>I/R', '     '), ' ', '');

สำหรับ XML ที่ไม่สำคัญมันอาจมีปัญหา


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