【问题标题】:XSLT Transforming when having multiple nodes with the same name具有多个同名节点时的 XSLT 转换
【发布时间】:2017-06-20 09:51:20
【问题描述】:

我有一个关于获取同名节点列表中每个元素的子元素值的问题(下例中的“b”元素)。

我在谷歌上搜索(和搜索该网站)的尝试没有产生任何结果。

我的实际 XML 更冗长,但我制作了一个简化版本,它确实重现了结果。它看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<a>
  <b>
    <c>
      <d>Value 1</d>
    </c>
  </b>
  <b>
    <c>
      <d>Value 2</d>
    </c>
  </b>
  <b>
    <c>
      <d>Value 3</d>
    </c>
  </b>
</a>

我想把它改成这样的结构:

<?xml version="1.0" encoding="UTF-8"?>
<docRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="our.urn.namespace our.xsd">
   <subEl>
      <value>Value 1</value>
   </subEl>
   <subEl>
      <value>Value 2</value>
   </subEl>
   <subEl>
      <value>Value 3</value>
   </subEl>
</docRoot>

我的 XSLT 如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/a/b/c/d/text()">
    <xsl:element name="value">
      <xsl:value-of select="/a/b/c/d"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="/a/b/c">
    <xsl:element name="subEl">
      <xsl:apply-templates select="./d/text()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="/">
    <xsl:element name="docRoot">
      <xsl:attribute name="xsi:schemaLocation">our.urn.namespace our.xsd</xsl:attribute>
      <xsl:apply-templates select="/a/b/c"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

但是,这会产生以下结果:

<?xml version="1.0" encoding="UTF-8"?>
<docRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="our.urn.namespace our.xsd">
   <subEl>
      <value>Value 1</value>
   </subEl>
   <subEl>
      <value>Value 1</value>
   </subEl>
   <subEl>
      <value>Value 1</value>
   </subEl>
</docRoot>

显然我没有正确选择这个。有谁知道获得所需输出的正确 xpath 吗?

注意:我也尝试过匹配“/”的模板

   <xsl:apply-templates select="/a/b"/>

而不是上面示例中的内容,然后我在它应用的模板中使用了 for-each,但结果没有变化。在我看来,这表明问题出在 xpath 上。 另外,为了可维护性,我宁愿不使用 for-each。

【问题讨论】:

    标签: xml xslt xpath


    【解决方案1】:

    尝试将前两个模板匹配合并到:

    <xsl:template match="/a/b/c">
      <xsl:element name="subEl">
        <xsl:element name="value">
          <xsl:value-of select="./d/text()"/>
        </xsl:element>
      </xsl:element>
    </xsl:template>
    

    编辑:如果你想要更接近你的方法,你可以做

      <xsl:template match="/a/b/c/d">
        <xsl:element name="value">
          <xsl:value-of select="text()"/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="/a/b/c">
        <xsl:element name="subEl">
          <xsl:apply-templates select="./d"/>
        </xsl:element>
      </xsl:template>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-16
      • 1970-01-01
      相关资源
      最近更新 更多