XSLT/XML 将节点的值复制到节点

XSLT/XML Copy value of node to node

我正在尝试将一个节点的节点内容复制到另一个节点。基本上节点内容应该和第一个节点一样,只是第二个节点的引号不要替换。

我找到了一些代码并修改了它,但是它只复制了第一个节点内容的第一次出现。

这是我到目前为止的 xslt 代码。

  <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="pReplacement" select="/strings/string/de/text()"/>

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

    <xsl:template match="strings/string/es/text()">
     <xsl:value-of select="$pReplacement"/>
    </xsl:template>
</xsl:stylesheet>

输入XML是:

 <?xml version="1.0"?>
 <?xml-stylesheet href="test.xsl" type="text/xsl"?>
  <strings>
    <string name="cpu">
        <en>example1</en>
        <de>something1</de>
        <es>""</es>
    </string>
    <string name="gpu">
        <en>example2</en>
        <de>something2</de>
        <es>""</es>
    </string>
    <string name="mainboard">
        <en>example3</en>
        <de>something3</de>
        <es>""</es>
    </string>
</strings>

错误的输出是:

<?xml-stylesheet href="test.xsl" type="text/xsl"?><strings>
  <string name="cpu">
    <en>example1</en>
    <de>something1</de>
    <es>something1</es>
  </string>
  <string name="gpu">
    <en>example2</en>
    <de>something2</de>
    <es>something1</es>
  </string>
  <string name="mainboard">
    <en>example3</en>
    <de>something3</de>
    <es>something1</es>
  </string>
</strings>

所需的输出应如下所示。

<?xml-stylesheet href="test.xsl" type="text/xsl"?><strings>
  <string name="cpu">
    <en>example1</en>
    <de>something1</de>
    <es>"something1"</es>
  </string>
  <string name="gpu">
    <en>example2</en>
    <de>something2</de>
    <es>"something2"</es>
  </string>
  <string name="mainboard">
    <en>example3</en>
    <de>something3</de>
    <es>"something3"</es>
  </string>
</strings>

也许有人可以帮助我找到解决方案或为我指明正确的方向。

非常感谢

您的方法无效,因为 XPath 表达式

/strings/string/de/text()

几个 个结果,在本例中为三个。如果你把它们放在这样的参数中:

<xsl:param name="pReplacement" select="/strings/string/de/text()"/>

然后所有三个结果节点将成为pReplacement的一部分。如果您在预期只有一个节点的地方使用一组节点,例如

<xsl:value-of select="$pReplacement"/>

那么只有第一个节点会被选中进行这个操作。

没有太多你需要改变的,只是取消top-level参数并将strings/string/es/text()的内容替换为

<xsl:value-of select="../../de"/>

XSLT 样式表

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="strings/string/es/text()">
     <xsl:value-of select="../../de"/>
    </xsl:template>

</xsl:stylesheet>

XML输出

<strings>
   <string name="cpu">
      <en>example1</en>
      <de>something1</de>
      <es>something1</es>
   </string>
   <string name="gpu">
      <en>example2</en>
      <de>something2</de>
      <es>something2</es>
   </string>
   <string name="mainboard">
      <en>example3</en>
      <de>something3</de>
      <es>something3</es>
   </string>
</strings>

在线尝试此解决方案 here


编辑

如果文档中的所有 es 元素都应受到此更改的影响,您还可以将模板编写为

<xsl:template match="es/text()">
  <xsl:value-of select="../preceding-sibling::de"/>
</xsl:template>

但这需要始终有一个 de 元素作为 string 元素的子元素,并且它始终在 es 元素之前。最后,如果在 es 元素之前有多个 de 元素,如果您使用 XSLT 2.0,这可能会成为问题,因为它会简单地连接前面所有 de 的字符串值元素。