XSLT-1.0 для установления отношений один-один - PullRequest
1 голос
/ 26 марта 2019

Я создал отчет, который отображает записи в стиле один ко многим. Однако мне нужно отобразить их как один-один. Я использовал XSLT для преобразования исходного XML, но он не работал.

Я разработал этот XSLT для преобразования XML.
Однако это не работает.

Это мой XML:

<?xml version="1.0" encoding="utf-16"?>
<Records count="2">
    <Record contentId="1442264" levelId="98" levelGuid="b085b230-e20f-41df- 
a849-f5d6811447ea" moduleId="167" parentId="0">
        <Record contentId="1608202" levelId="155" levelGuid="20b8e343-96c0-4aed- 
804c-7e40b489f31b" moduleId="537" parentId="0">
            <Field id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" 
type="6">16913</Field>
            <Field id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" 
type="6">1608202</Field>
        </Record>
        <Record contentId="1608204" levelId="155" levelGuid="20b8e343-96c0-4aed- 
804c-7e40b489f31b" moduleId="537" parentId="0">
            <Field id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" 
type="6">16915</Field>
            <Field id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" 
type="6">1608204</Field>
        </Record>
        <Field id="2260" guid="a69370c5-b6a7-4e20-a073-dd6bbd131e43" 
type="6">1442264</Field>
    </Record>
    <Record contentId="1445144" levelId="98" levelGuid="b085b230-e20f-41df- 
a849-f5d6811447ea" moduleId="167" parentId="0">
        <Record contentId="1608203" levelId="155" levelGuid="20b8e343-96c0-4aed- 
804c-7e40b489f31b" moduleId="537" parentId="0">
            <Field id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" 
type="6">16914</Field>
            <Field id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" 
type="6">1608203</Field>
        </Record>
        <Record contentId="1608205" levelId="155" levelGuid="20b8e343-96c0-4aed- 
804c-7e40b489f31b" moduleId="537" parentId="0">
            <Field id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" 
type="6">16916</Field>
            <Field id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" 
type="6">1608205</Field>
        </Record>
        <Field id="2260" guid="a69370c5-b6a7-4e20-a073-dd6bbd131e43" 
type="6">1445144</Field>
    </Record>
    <Metadata>
        <FieldDefinitions>
            <FieldDefinition id="2260" guid="a69370c5-b6a7-4e20-a073-dd6bbd131e43" 
name="Issue ID" alias="Finding_ID" />
            <FieldDefinition id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" 
name="CAP ID" alias="Remediation_Plan_ID" />
            <FieldDefinition id="17182" guid="e950ebab-1bf6-4fc8-818b-88a54fd12f89" 
name="CAP Title" alias="Name" />
            <FieldDefinition id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" 
name="X - Tracking ID" alias="X__Tracking_ID" />
        </FieldDefinitions>
    </Metadata>
    <LevelCounts>
        <LevelCount id="98" guid="b085b230-e20f-41df-a849-f5d6811447ea" count="2" 
/>
        <LevelCount id="155" guid="20b8e343-96c0-4aed-804c-7e40b489f31b" 
count="4" />
    </LevelCounts>
</Records>

А это мой XSLT:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns="http://www.archer-tech.com/">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/">
        <ArcherRecords>
            <xsl:for-each select="Records/Record/Field[@guid='b085b230-e20f-41df- 
 a849-f5d6811447ea']/Reference">
                <ArcherRecord>
                    <IssueID>
                        <xsl:value-of select="."/>
                    </IssueID>
                    <CAPID>
                        <xsl:value-of select="../../Field[@guid='ed20bfb9-d2e9-44c2-9b22- 
 5e39d26beae4']"/>
                    </CAPID>
                    <XTrackingID>
                        <xsl:value-of select="../../Field[@guid='d378d42e-42da- 
 4a23-906a-722fcb7d761e']"/>
                    </XTrackingID>
                </ArcherRecord>
            </xsl:for-each>
        </ArcherRecords>
    </xsl:template>

</xsl:stylesheet>

Мой ввод:

Issue ID                  CAP ID          X - Tracking ID
Issue-1442264             CAP-16913       1608202
                          CAP-16915       1608204
Issue-1445144             CAP-16914       1608203
                          CAP-16916       1608205

И ожидаемый результат:

Issue ID           CAP ID       X - Tracking ID
Issue-1442264      CAP-16913    1608202
Issue-1442264      CAP-16915    1608204
Issue-1445144      CAP-16914    1608203
Issue-1445144      CAP-16916    1608205

Фактический результат:

 <?xml version="1.0" encoding="UTF-8"?>
 <ArcherRecords xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.archer-tech.com/"/>

Ответы [ 2 ]

0 голосов
/ 27 марта 2019

Вам просто нужно найти one вашего отношения XML "один-много", а затем выполнить итерацию many для создания нового элемента XML.

.xsl

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    exclude-result-prefixes="msxsl" xmlns="http://www.archer-tech.com/">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="/">
        <ArcherRecords>
            <xsl:for-each select='//Record[@levelGuid="b085b230-e20f-41df-a849-f5d6811447ea"]'>
              <xsl:param name="issueid">
                    <xsl:value-of select="Field[@guid='a69370c5-b6a7-4e20-a073-dd6bbd131e43']"></xsl:value-of>
                </xsl:param>
                <xsl:for-each select="Record">
                    <ArcherRecord>
                        <IssueID>Issue-<xsl:value-of select="$issueid"></xsl:value-of>
                        </IssueID>
                        <CAPID>CAP-<xsl:value-of select="Field[@guid='ed20bfb9-d2e9-44c2-9b22-5e39d26beae4']" />
                        </CAPID>
                        <XTrackingID>
                            <xsl:value-of select="Field[@guid='d378d42e-42da-4a23-906a-722fcb7d761e']" />
                        </XTrackingID>
                    </ArcherRecord>
                </xsl:for-each>
            </xsl:for-each>
        </ArcherRecords>
    </xsl:template>
</xsl:stylesheet>

Результат в соответствии с вашим XML идет к

<ArcherRecords>
    <ArcherRecord>
        <IssueID>Issue-1442264</IssueID>
        <CAPID>CAP-16913</CAPID>
        <XTrackingID>1608202</XTrackingID>
    </ArcherRecord>
    <ArcherRecord>
        <IssueID>Issue-1442264</IssueID>
        <CAPID>CAP-16915</CAPID>
        <XTrackingID>1608204</XTrackingID>
    </ArcherRecord>
    <ArcherRecord>
        <IssueID>Issue-1445144</IssueID>
        <CAPID>CAP-16914</CAPID>
        <XTrackingID>1608203</XTrackingID>
    </ArcherRecord>
    <ArcherRecord>
        <IssueID>Issue-1445144</IssueID>
        <CAPID>CAP-16916</CAPID>
        <XTrackingID>1608205</XTrackingID>
    </ArcherRecord>
</ArcherRecords>

Исправлены разрывы строк XML:

<?xml version="1.0" encoding="utf-16"?>
<Records count="2">
    <Record contentId="1442264" levelId="98" levelGuid="b085b230-e20f-41df-a849-f5d6811447ea" moduleId="167" parentId="0">
        <Record contentId="1608202" levelId="155" levelGuid="20b8e343-96c0-4aed-804c-7e40b489f31b" moduleId="537" parentId="0">
            <Field id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" type="6">16913</Field>
            <Field id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" type="6">1608202</Field>
        </Record>
        <Record contentId="1608204" levelId="155" levelGuid="20b8e343-96c0-4aed-804c-7e40b489f31b" moduleId="537" parentId="0">
            <Field id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" type="6">16915</Field>
            <Field id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" type="6">1608204</Field>
        </Record>
        <Field id="2260" guid="a69370c5-b6a7-4e20-a073-dd6bbd131e43" type="6">1442264</Field>
    </Record>
    <Record contentId="1445144" levelId="98" levelGuid="b085b230-e20f-41df-a849-f5d6811447ea" moduleId="167" parentId="0">
        <Record contentId="1608203" levelId="155" levelGuid="20b8e343-96c0-4aed-804c-7e40b489f31b" moduleId="537" parentId="0">
            <Field id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" type="6">16914</Field>
            <Field id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" type="6">1608203</Field>
        </Record>
        <Record contentId="1608205" levelId="155" levelGuid="20b8e343-96c0-4aed-804c-7e40b489f31b" moduleId="537" parentId="0">
            <Field id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" type="6">16916</Field>
            <Field id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" type="6">1608205</Field>
        </Record>
        <Field id="2260" guid="a69370c5-b6a7-4e20-a073-dd6bbd131e43" type="6">1445144</Field>
    </Record>
    <Metadata>
        <FieldDefinitions>
            <FieldDefinition id="2260" guid="a69370c5-b6a7-4e20-a073-dd6bbd131e43" name="Issue ID" alias="Finding_ID" />
            <FieldDefinition id="17169" guid="ed20bfb9-d2e9-44c2-9b22-5e39d26beae4" name="CAP ID" alias="Remediation_Plan_ID" />
            <FieldDefinition id="17182" guid="e950ebab-1bf6-4fc8-818b-88a54fd12f89" name="CAP Title" alias="Name" />
            <FieldDefinition id="27556" guid="d378d42e-42da-4a23-906a-722fcb7d761e" name="X - Tracking ID" alias="X__Tracking_ID" />
        </FieldDefinitions>
    </Metadata>
    <LevelCounts>
        <LevelCount id="98" guid="b085b230-e20f-41df-a849-f5d6811447ea" count="2" />
        <LevelCount id="155" guid="20b8e343-96c0-4aed-804c-7e40b489f31b" count="4" />
    </LevelCounts>
</Records>
0 голосов
/ 27 марта 2019

Основная причина, по которой ваш XSLT дает сбой, заключается в том, что и ваш XML, и XSLT имеют неправильную обработку пробелов. Из-за этого выражения не совпадают!

Решение исправление разрывов строк !

Например:
Ваш соответствующий атрибут levelGuid содержит разрыв строки и некоторые пробелы, которые делают (почти) невозможным сопоставление строковым значением подключенного выражения XPath.

Так что вам придется столкнуться с неудобной задачей исправления разрывов строк в вашем XML.


После того, как вы исправили ситуацию с разрывом строки, следующий код XSLT-1.0 даст вам несколько полезных выводов:

<xsl:template match="/Records">
    <ArcherRecords>
        <xsl:for-each select="Record[@levelGuid='b085b230-e20f-41df-a849-f5d6811447ea']">
            <ArcherRecord>
                <IssueID>
                    <xsl:value-of select="@contentId"/>
                </IssueID>
                <xsl:for-each select="Record">
                    <CAPID>
                        <xsl:value-of select="Field[@guid='ed20bfb9-d2e9-44c2-9b22-5e39d26beae4']"/>
                    </CAPID>
                    <XTrackingID>
                        <xsl:value-of select="Field[@guid='d378d42e-42da-4a23-906a-722fcb7d761e']"/>
                    </XTrackingID>
                </xsl:for-each>
            </ArcherRecord>
        </xsl:for-each>
    </ArcherRecords>
</xsl:template>

Его вывод:

<?xml version="1.0"?>
<ArcherRecords xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:arch="http://www.archer-tech.com/">
    <ArcherRecord>
        <IssueID>1442264</IssueID>
        <CAPID>16913</CAPID>
        <XTrackingID>1608202</XTrackingID>
        <CAPID>16915</CAPID>
        <XTrackingID>1608204</XTrackingID>
    </ArcherRecord>
    <ArcherRecord>
        <IssueID>1445144</IssueID>
        <CAPID>16914</CAPID>
        <XTrackingID>1608203</XTrackingID>
        <CAPID>16916</CAPID>
        <XTrackingID>1608205</XTrackingID>
    </ArcherRecord>
</ArcherRecords>

Это ответ на ваш вопрос.
Теперь осталось получить чистый текстовый вывод.
И шаблон для создания желаемого вывода:

<xsl:output method="text" indent="yes" />

<xsl:template match="/Records">
    <xsl:text>Issue ID&#x9;CAP ID&#x9;&#x9;X - Tracking ID&#xa;</xsl:text>
    <xsl:for-each select="Record[@levelGuid='b085b230-e20f-41df-a849-f5d6811447ea']">
        <xsl:for-each select="Record">
            <xsl:value-of select="concat('Issue-',../@contentId)"/><xsl:text>&#x9;</xsl:text>
            <xsl:value-of select="concat('CAP-',Field[@guid='ed20bfb9-d2e9-44c2-9b22-5e39d26beae4'])"/><xsl:text>&#x9;</xsl:text>
            <xsl:value-of select="Field[@guid='d378d42e-42da-4a23-906a-722fcb7d761e']"/>
            <xsl:text>&#x9;&#xa;</xsl:text>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

Его вывод:

Issue ID        CAP ID          X - Tracking ID
Issue-1442264   CAP-16913       1608202
Issue-1442264   CAP-16915       1608204
Issue-1445144   CAP-16914       1608203
Issue-1445144   CAP-16916       1608205
...