1

您好我需要帮助解析以下 XML。

<xmeml>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>1234</Unit2>
    </Test>
    <Test>
        <Unit>bcd</Unit>
        <Unit2>2345</Unit2>
    </Test>
</Doc>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>3456</Unit2>
    </Test>
    <Test>
        <Unit>cde</Unit>
        <Unit2>3456</Unit2>
    </Test> 
</Doc>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>1234</Unit2>
    </Test>
    <Test>
        <Unit>def</Unit>
        <Unit2>4567</Unit2>
    </Test> 
</Doc>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>1234</Unit2>
    </Test>
    <Test>
        <Unit>efg</Unit>
        <Unit2>2345</Unit2>
    </Test> 
</Doc>
</xmeml>

以以下结束

<xmeml>
<Doc>
    <Test>
        <Unit>bcd</Unit>
        <Unit2>2345</Unit2>
    </Test>
</Doc>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>3456</Unit2>
    </Test>
    <Test>
        <Unit>cde</Unit>
        <Unit2>3456</Unit2>
    </Test> 
</Doc>
<Doc>
    <Test>
        <Unit>def</Unit>
        <Unit2>4567</Unit2>
    </Test> 
</Doc>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>1234</Unit2>
    </Test>
    <Test>
        <Unit>efg</Unit>
        <Unit2>2345</Unit2>
    </Test> 
</Doc>
</xmeml>

我正在尝试创建一个 XSLT 文档来执行此操作,但尚未找到一个有效的文档。我应该注意到 are 中所需的匹配参数,在本例中为“abc”,是变量,永远不会是静态可搜索实体。

所以用英文我的 XSL 会是这样的:对于任何包含匹配“Unit”值的父级,删除所有前面的父级“Test”,其中包含“Unit”中的重复值,除了最后一个。

非常感谢所有帮助谢谢

4

2 回答 2

2

您可以使用标识模板复制整个文档,并使用您要删除的元素的空模板覆盖该模板。为了检查一个<Test>元素是否应该被删除,您可以将其<Unit>值与以下兄弟元素的值进行比较。

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

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/xmeml/Doc/Test[(Unit = following-sibling::Test/Unit) or (Unit = ../following-sibling::Doc/Test/Unit)][descendant::Unit2[starts-with(.,'1234')]]"/>

</xsl:stylesheet>

由于以下值如何出现有两种可能性,因此<Unit>这两个条件都被显式编写并与or条件中的运算符连接。

这两种可能性及其各自的 XPath 条件是:

  • <Test>在与当前元素相同的父元素中的后续元素中:
    Unit = following-sibling::Test/Unit
  • 在当前元素<Test>的后续<Doc>兄弟元素中<Doc>
    Unit = ../following-sibling::Doc/Test/Unit

假设这个输入:

<xmeml>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>1234</Unit2>
    </Test>
    <Test>
        <Unit>bcd</Unit>
        <Unit2>2345</Unit2>
    </Test>
</Doc>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>3456</Unit2>
    </Test>
    <Test>
        <Unit>cde</Unit>
        <Unit2>3456</Unit2>
    </Test> 
</Doc>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>1234</Unit2>
    </Test>
    <Test>
        <Unit>def</Unit>
        <Unit2>4567</Unit2>
    </Test> 
</Doc>
<Doc>
    <Test>
        <Unit>abc</Unit>
        <Unit2>1234</Unit2>
    </Test>
    <Test>
        <Unit>efg</Unit>
        <Unit2>2345</Unit2>
    </Test> 
</Doc>
</xmeml>

XSLT 创建以下输出:

<xmeml>
  <Doc>
    <Test>
      <Unit>bcd</Unit>
      <Unit2>2345</Unit2>
    </Test>
  </Doc>
  <Doc>
    <Test>
      <Unit>abc</Unit>
      <Unit2>3456</Unit2>
    </Test>
    <Test>
      <Unit>cde</Unit>
      <Unit2>3456</Unit2>
    </Test>
  </Doc>
  <Doc>
    <Test>
      <Unit>def</Unit>
      <Unit2>4567</Unit2>
    </Test>
  </Doc>
  <Doc>
    <Test>
      <Unit>abc</Unit>
      <Unit2>1234</Unit2>
    </Test>
    <Test>
      <Unit>efg</Unit>
      <Unit2>2345</Unit2>
    </Test>
  </Doc>
</xmeml>
于 2012-07-20T09:11:21.573 回答
1

在 XSLT 1.0 中执行分组有两种不同的方法——简单,使用preceding::orfollowing::轴,以及更有效的 Muenchian 分组方法——使用键。

这是更有效的 Muenchian 方法:

<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:key name="kParentByUnit" match="Test[Unit]" use="Unit"/>

     <xsl:template match="node()|@*" name="identity">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>

     <xsl:template match="Test[Unit]">
       <xsl:if test=
       "generate-id()
       =
        generate-id(key('kParentByUnit', Unit)[position()=last()])">

        <xsl:call-template name="identity"/>
       </xsl:if>
     </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<xmeml>
    <Doc>
        <Test>
            <Unit>abc</Unit>
            <Unit2>1234</Unit2>
        </Test>
        <Test>
            <Unit>bcd</Unit>
            <Unit2>2345</Unit2>
        </Test>
    </Doc>
    <Doc>
        <Test>
            <Unit>abc</Unit>
            <Unit2>3456</Unit2>
        </Test>
        <Test>
            <Unit>cde</Unit>
            <Unit2>3456</Unit2>
        </Test>
    </Doc>
    <Doc>
        <Test>
            <Unit>abc</Unit>
            <Unit2>1234</Unit2>
        </Test>
        <Test>
            <Unit>def</Unit>
            <Unit2>4567</Unit2>
        </Test>
    </Doc>
    <Doc>
        <Test>
            <Unit>abc</Unit>
            <Unit2>1234</Unit2>
        </Test>
        <Test>
            <Unit>efg</Unit>
            <Unit2>2345</Unit2>
        </Test>
    </Doc>
</xmeml>

产生了想要的正确结果

<xmeml>
   <Doc>
      <Test>
         <Unit>bcd</Unit>
         <Unit2>2345</Unit2>
      </Test>
   </Doc>
   <Doc>
      <Test>
         <Unit>cde</Unit>
         <Unit2>3456</Unit2>
      </Test>
   </Doc>
   <Doc>
      <Test>
         <Unit>def</Unit>
         <Unit2>4567</Unit2>
      </Test>
   </Doc>
   <Doc>
      <Test>
         <Unit>abc</Unit>
         <Unit2>1234</Unit2>
      </Test>
      <Test>
         <Unit>efg</Unit>
         <Unit2>2345</Unit2>
      </Test>
   </Doc>
</xmeml>
于 2012-07-20T12:16:46.217 回答