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

时间:2016-01-04 13:56:16

标签: xml xslt xslt-1.0

我正在尝试将一个节点的节点内容复制到另一个节点。基本上节点内容应该与第一个节点中的相同,除了不应该替换第二个节点中的引号。

我找到了一些代码并对其进行了修改,但它只复制了第一个节点内容的第一个外观。

这是我到目前为止的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>

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

非常感谢提前

1 个答案:

答案 0 :(得分:1)

您的方法不起作用,因为XPath表达式

/strings/string/de/text()

几个结果,在这种情况下有三个。如果你把它们放在这样的参数中:

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

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

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

然后只为此操作选择 first 节点。

您无需更改,只需取消顶级参数并将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元素之前。最后,如果在de元素之前有多个es元素,如果您使用的是XSLT 2.0,则可能会出现问题,因为它只会连接前面所有de的字符串值元件。