我有一个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>
答案 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])
为每个组选择适当的元素包装器。