-1

我有一个 XML 我想用 xslt 转换它。输入看起来像这样。

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

输出应该是这样的。

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

我想删除任何符合以下条件的测试节点。- Unit3 子节点以 tuv 或 uvw 开头。- AND 其中 Unit 和 Unit2 的值都在另一个测试节点中被发现重复/重复

在此先感谢您的帮助。

4

2 回答 2

1

这种转换(基于 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="kTest"
   match="Test[starts-with(Unit3, 'tuv') or starts-with(Unit3, 'uvw')]"
          use="concat(Unit, '+', Unit2)"/>

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

 <xsl:template match=
  "Test[starts-with(Unit3, 'tuv') or starts-with(Unit3, 'uvw')]
    [not(generate-id()
    =
     generate-id(key('kTest', concat(Unit, '+', Unit2))[last()]))]"/>
</xsl:stylesheet>

应用于提供的 XML 文档时

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

产生正确的结果(实现所有要求):

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

更新

OP对这个问题有自己的解释,这是模棱两可的,没有精确定义。

有了相当多的猜测,这就是他可能想要的……:

<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="kTest"
   match="Test" use="concat(Unit, '+', Unit2)"/>

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

 <xsl:template match=
  "Test[starts-with(Unit3, 'tuv') or starts-with(Unit3, 'uvw')]
    [not(generate-id()
    =
     generate-id(key('kTest', concat(Unit, '+', Unit2))
                                     [not(position()=1)])
                )]"/>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档(上图)时,现在结果与 OP 认为是想要的结果相同

<xmeml>
   <Doc>
      <Test>
         <Unit>bcd</Unit>
         <Unit2>2345</Unit2>
         <Unit3>wxyz</Unit3>
      </Test>
   </Doc>
   <Doc>
      <Test>
         <Unit>abc</Unit>
         <Unit2>3456</Unit2>
         <Unit3>wxyz</Unit3>
      </Test>
      <Test>
         <Unit>cde</Unit>
         <Unit2>3456</Unit2>
         <Unit3>wxyz</Unit3>
      </Test>
   </Doc>
   <Doc>
      <Test>
         <Unit>abc</Unit>
         <Unit2>1234</Unit2>
         <Unit3>wxyz</Unit3>
      </Test>
      <Test>
         <Unit>def</Unit>
         <Unit2>4567</Unit2>
         <Unit3>wxyz</Unit3>
      </Test>
   </Doc>
   <Doc>
      <Test>
         <Unit>efg</Unit>
         <Unit2>2345</Unit2>
         <Unit3>wxyz</Unit3>
      </Test>
   </Doc>
</xmeml>
于 2012-07-22T03:19:01.943 回答
1

Dimitre 的解决方案的这个调整怎么样......

<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="kTest" match="Test" use="concat(Unit, '+', Unit2)"/>

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

 <xsl:template match=
  "Test[key('kTest', concat(Unit, '+', Unit2))[2]]
   [starts-with(Unit3, 'tuv') or starts-with(Unit3, 'uvw')]"/>
</xsl:stylesheet>

据我了解,转换规则是:

  1. 照原样复制所有节点,除非如下所示。
  2. 排除所有测试节点具有以下属性:

2.1 文档中存在另一个测试节点(称为 Test(other)),这样:

  (Test(reference) / Unit = Test(other) / Unit)   AND
  (Test(reference) / Unit2 = Test(other) / Unit2)

2.2 引用Test节点的Unit3子节点以tuv或uvw开头

输出与 OP 发布的完全相同。有趣的是,如果我正确理解了这个问题,Dimitre 最近刚刚提供了一个解决方案来解决与您在XSL 节点比较中几乎相同的问题。同样,如果我正确理解了您的问题,则标题具有误导性。“删除重复项”通常表示重复数据删除,如 (1,2,2,3) --> (1,2,3) ;而您想要的,例如 (1,2,2,3) --> (1,3) 通常被描述为“选择唯一节点/值”。

于 2012-07-22T06:24:05.280 回答