【发布时间】:2022-01-06 10:37:28
【问题描述】:
我需要使用 XPATH 将新的 XML 节点添加到现有的 XML。
现有的 XML:
<create>
<article>
<identifier>Test</identifier>
</article>
</create>
XSLT Used (Get if from another thread in stackoverflow):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vPop" as="element()*">
<item path="/create/article[1]/id">1</item>
<item path="/create/article[1]/description">bar</item>
<item path="/create/article[1]/name[1]">foo</item>
<item path="/create/article[1]/price[1]/amount">00.00</item>
<item path="/create/article[1]/price[1]/currency">USD</item>
<item path="/create/article[1]/price[2]/amount">11.11</item>
<item path="/create/article[1]/price[2]/currency">AUD</item>
<item path="/create/article[2]/id">2</item>
<item path="/create/article[2]/description">some name</item>
<item path="/create/article[2]/name[1]">some description</item>
<item path="/create/article[2]/price[1]/amount">00.01</item>
<item path="/create/article[2]/price[1]/currency">USD</item>
</xsl:variable>
<xsl:template match="/">
<xsl:sequence select="my:subTree($vPop/@path/concat(.,'/',string(..)))"/>
</xsl:template>
<xsl:function name="my:subTree" as="node()*">
<xsl:param name="pPaths" as="xs:string*"/>
<xsl:for-each-group select="$pPaths"
group-adjacent=
"substring-before(substring-after(concat(., '/'), '/'), '/')">
<xsl:if test="current-grouping-key()">
<xsl:choose>
<xsl:when test=
"substring-after(current-group()[1], current-grouping-key())">
<xsl:element name=
"{substring-before(concat(current-grouping-key(), '['), '[')}">
<xsl:sequence select=
"my:subTree(for $s in current-group()
return
concat('/',substring-after(substring($s, 2),'/'))
)
"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="current-grouping-key()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:for-each-group>
</xsl:function>
</xsl:stylesheet>
使用上面的 XSLT,XPATH 被转换为 XML 节点。但问题是现有的 XML 节点 (<identifier>Test</identifier>) 丢失了。请帮助解决此问题。这是一个示例 XML,实际的 XML 包含许多现有的 XML 节点。
实际结果:
<create>
<article>
<id>1</id>
<description>bar</description>
<name>foo</name>
<price>
<amount>00.00</amount>
<currency>USD</currency>
</price>
<price>
<amount>11.11</amount>
<currency>AUD</currency>
</price>
</article>
<article>
<id>2</id>
<description>some name</description>
<name>some description</name>
<price>
<amount>00.01</amount>
<currency>USD</currency>
</price>
</article>
</create>
预期结果:
<create>
<article>
<identifier>Test</identifier>
<id>1</id>
<description>bar</description>
<name>foo</name>
<price>
<amount>00.00</amount>
<currency>USD</currency>
</price>
<price>
<amount>11.11</amount>
<currency>AUD</currency>
</price>
</article>
<article>
<id>2</id>
<description>some name</description>
<name>some description</name>
<price>
<amount>00.01</amount>
<currency>USD</currency>
</price>
</article>
</create>
【问题讨论】:
-
from 创建元素 XPath 是一种奇怪的(并且从根本上被破坏的)生成 XML 的方式。这样做有什么意义?谁编写了您用来生成 XML 的 XPath?
-
如果主输入具有例如,决定形成哪个值的规则是什么?一个元素
/create/article[1]/id并且您的带有 XPaths 的变量也想添加它? -
@Tomalak 理想情况下,要求是动态地将新字段添加到文档中。在开发期间,开发人员并不了解这些领域。因此,我们将这些字段作为 XPATH 存储在缓存中。在运行时,我们将为该文档创建一个基于 XML 的 XML,然后从存储在缓存中的 XPATH 创建这些新字段。
-
@MartinHonnen 如果主输入中已经存在相同的元素,则 XPATH 中的变量可以覆盖它。
-
再次。这是一个从根本上被破坏的设计。它不聪明,没有必要,不可扩展,不可持续——这不是一个好主意。你真的应该重新工作这部分。如果您可以编写 XPath 来“存储”有关 XML 的结构信息,那么您也可以直接编写 XML。
标签: xml xslt xsd xslt-2.0 xslt-3.0