【问题标题】:XSLT 1.0 All Nodes between two different nodesXSLT 1.0 两个不同节点之间的所有节点
【发布时间】:2019-04-10 06:31:45
【问题描述】:

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

我很清楚如何在标题(客户、用户)下获取子数据,但我真的很纠结如何在两个不同命名的节点(包括这些节点)之间进行选择。我真的在寻找允许选择这些区域的 XPath。

所以对于Customer节点,我需要通过UserName之前的节点在CustomerName之间进行选择(实际数据中的节点要多得多)。然后对于每个用户(其中​​的数量未知),我需要在 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>

【问题讨论】:

  • 这类似于:stackoverflow.com/questions/33448325/… -- P.S.请提供一个有用的例子。 1 不是有效的元素名称。
  • 1 无关紧要,我只是将它们用作占位符。我会看看链接的问题是否适合我。
  • 这对于我们任何想要使用您的代码进行测试以便为您提供答案的人来说都很重要。请节省我们的时间。
  • 我更新了 XML。链接的问题使用 for-each-group 如果节点都具有相同的子节点,这似乎有效,但它们不会,而且我不知道我需要分隔的节点之间有哪些节点。跨度>
  • 试试&lt;xsl:for-each-group select="*" group-starting-with="UserName"&gt;

标签: xml xslt xpath


【解决方案1】:

以下是您如何在 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

【讨论】:

    猜你喜欢
    • 2018-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 2019-04-19
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多