XSLT 1.0两个不同节点之间的所有节点

时间:2018-11-06 19:58:10

标签: xml xslt xpath

我有一个XML节点列表,需要将其转换为某种结构化数据,但遇到了一些麻烦。

我对如何在标题(客户,用户)下获取子数据有一个很好的主意,但是我真的在如何在两个不同名称的节点(包括那些节点)之间进行选择方面苦苦挣扎。我真的在寻找允许选择这些区域的XPath。

因此对于Customer节点,我需要在UserName之前的CustomerName到NodeName之间进行选择(实际数据中还有更多节点)。然后,对于每个用户(数量未知),我需要在UserName和下一个UserName之前的节点之间切换,再次在真实数据中包含两个以上的节点。

我试图使用前兄弟,后兄弟和计数的组合,但是我只是无法正确地进行工作。任何指向正确方向的指针都会有很大帮助。

我更喜欢XSLT 1.0,但是我可以使用2.0。

示例数据:

<Data>
  <CustomerName>
    <Name>ABCCompany</Name>
  </CustomerName>
  <CustomerAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
  </CustomerAddress>
  <UserName>
    <Name>Betty<Name>
  </UserName>
  <UserAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
  </UserAddress>
  <UserName>
    <Name>Johnny</Name>
  </UserName>
  <UserAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
  </UserAddress>
</Data>

所需的输出:

<Data>
  <Customer>
    <CustomerName>
      <Name>ABCCompany</Name>
    </CustomerName>
    <CustomerAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
    </CustomerAddress>
  </Customer>
  <Users>
    <User>
      <UserName>
        <Name>Betty</Name>
      </UserName>
      <UserAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
      </UserAddress>
    </User>
    <User>
      <UserName>
        <Name>Johnny</Name>
      </UserName>
      <UserAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
      </UserAddress>
    </User>
  </Users>
</Data>

1 个答案:

答案 0 :(得分:2)

这是您如何在 XSLT 2.0 中实现此目标的粗略原型:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/Data">
    <xsl:copy>
        <xsl:for-each-group select="*" group-starting-with="CustomerName|UserName">
            <group type="{name(current-group()[1])}">
                <xsl:copy-of select="current-group()" />
            </group>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

应用于您的示例输入(已纠正格式错误!),结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<Data>
   <group type="CustomerName">
      <CustomerName>
         <Name>ABCCompany</Name>
      </CustomerName>
      <CustomerAddress>
         <City>AnyCity</City>
         <State>AnyState</State>
      </CustomerAddress>
   </group>
   <group type="UserName">
      <UserName>
         <Name>Betty</Name>
      </UserName>
      <UserAddress>
         <City>AnyCity</City>
         <State>AnyState</State>
      </UserAddress>
   </group>
   <group type="UserName">
      <UserName>
         <Name>Johnny</Name>
      </UserName>
      <UserAddress>
         <City>AnyCity</City>
         <State>AnyState</State>
      </UserAddress>
   </group>
</Data>

您可以使用表达式name(current-group()[1])为每个组选择适当的元素包装器。


演示:http://xsltransform.hikmatu.com/bdxtpC