Добавить новый xml-узел к существующим xml-узлам с помощью xslt

#xslt

#xslt

Вопрос:

Я пытаюсь добавить новый XML-узел в существующий XML-узел, но мне не удалось достичь желаемого результата.

Пожалуйста, найдите мой приведенный ниже XML,

     <Root>
        <Row>
            <A1>0</A1>
            <A2>1</A2>
            <Preferred_First_Name>aaaa</Preferred_First_Name>
            <Preferred_Last_Name>yyyy</Preferred_Last_Name>
            <location>xxxx</location>
            <ID>12345</ID>
        </Row>
    </Root>
  

Я хочу изменить приведенный выше XML таким образом, чтобы Preferred_First_Name, Preferred_Last_Name и узел location должны были находиться под новым XML-тегом «Data».

Желаемый результат должен быть таким, как показано ниже,

 <Root>
    <Row>
        <A1>0</A1>
        <A2>1</A2>
        <Data>
            <Preferred_First_Name>aaaa</Preferred_First_Name>
            <Preferred_Last_Name>yyyy</Preferred_Last_Name>
            <location Descriptor="xxxx">
                <ID type="ID">xxxx</ID>
                <ID type="LocationID">xxxx</ID>
            </location>
        </Data>
        <ID>12345</ID>
    </Row>
</Root>
  

Кто-нибудь, пожалуйста, может помочь?

Комментарии:

1. Можете ли вы отредактировать свой вопрос, чтобы показать свою попытку, поскольку вы, возможно, на самом деле не за горами! Кроме того, имеет ли значение, если Data элемент получил append после ID , а не раньше? Спасибо!

Ответ №1:

вы можете использовать ниже

 <?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet xmlns:xalan="http://xml.apache.org/xalan" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:template match="Root">
        <xsl:element name="Root">
            <xsl:call-template name="Row" />
        </xsl:element>
    </xsl:template>
    <xsl:template name="Row">
        <xsl:element name="Row">
            <xsl:copy-of select="Row/A1"/>
            <xsl:copy-of select="Row/A2"/>
            <xsl:element name="Data">
            <xsl:copy-of select="Row/Preferred_First_Name"/>
            <xsl:copy-of select="Row/Preferred_Last_Name"/>
            <xsl:element name="location">
                <xsl:attribute name="Descriptor">
                    <xsl:value-of select="Row/location"/>
                </xsl:attribute>
                <xsl:element name="ID">
                    <xsl:attribute name="type">
                        <xsl:value-of select="'ID'"/>
                    </xsl:attribute>
                    <xsl:value-of select="Row/location"/>
                </xsl:element>
            <xsl:element name="ID">
                <xsl:attribute name="type">
                    <xsl:value-of select="'LocationID'"/>
                </xsl:attribute>
                <xsl:value-of select="Row/location"/>
            </xsl:element>
            </xsl:element>
                    <xsl:copy-of select="Row/ID"/>
        </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>
  

Пожалуйста, дайте мне знать, что это поможет вам

Комментарии:

1. Старайтесь, когда это возможно, использовать элементы literal result: это делает таблицу стилей менее подробной и упрощает обслуживание.

Ответ №2:

Если можно поставить <ID> после <Data> упоминания Тима Си, то оптимизированное решение может быть:

 <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Row">
    <Row>
        <xsl:apply-templates select="child::node()[not(self::Preferred_First_Name or self::Preferred_Last_Name
                                                    or self::location)]" />
        <Data>
             <xsl:apply-templates select="child::node()[self::Preferred_First_Name or self::Preferred_Last_Name
                                                    or self::location]"/>  
        </Data>
    </Row>
</xsl:template>

</xsl:stylesheet>
  

Комментарии:

1. Большое спасибо Вебби, это решение также отлично работает.

2. Кстати, второй xsl:apply-templates можно упростить до <xsl:apply-templates select=":Preferred_First_Name|Preferred_Last_Name|location" /> . 🙂

3. @TimC : Да. Спасибо вам за дополнительную оптимизацию. 🙂

4. Кроме того, в этом контексте child::node() может быть только * .