#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()
может быть только*
.