使用XSL 1.0报告重复或非重复节点

时间:2014-02-11 18:57:27

标签: xml xslt xpath xslt-1.0

使用XSLT 1.0我需要查找是否存在重复节点,或者是tofrom类别中的单个节点。

我发现这个XSL comparison of nodes非常相似,但也无法使其发挥作用。

XML:

    <acl>
      <enabled>true</enabled>
      <from>
        <rule>
          <name>1.1.1.1</name>
          <pattern>1.1.1.1</pattern>
          <allow/>
          <log>true</log>
          <alarm>0</alarm>
        </rule>
        <rule>
          <name>1.1.1.3</name>
          <pattern>1.1.1.3</pattern>
          <allow/>
          <log>false</log>
          <alarm>0</alarm>
        </rule>
        <rule>
          <name>1.1.1.4</name>
          <pattern>1.1.1.4</pattern>
          <deny/>
          <log>true</log>
          <alarm>0</alarm>
        </rule>
        <fallthrough>
          <allow/>
          <log>true</log>
          <alarm>0</alarm>
        </fallthrough>
      </from>
      <to>
        <rule>
          <name>1.1.1.2</name>
          <pattern>1.1.1.2</pattern>
          <allow/>
          <log>true</log>
          <alarm>0</alarm>
        </rule>
        <rule>
          <name>1.1.1.3</name>
          <pattern>1.1.1.3</pattern>
          <allow/>
          <log>false</log>
          <alarm>0</alarm>
        </rule>
        <rule>
          <name>1.1.1.4</name>
          <pattern>1.1.1.4</pattern>
          <deny/>
          <log>true</log>
          <alarm>0</alarm>
        </rule>
        <fallthrough>
          <allow/>
          <log>false</log>
          <alarm>0</alarm>
        </fallthrough>
      </to>
    </acl>

期望的结果:

1.1.1.1将显示&#34;来自&#34; (它来自from部分)

1.1.1.3将显示&#34;两者&#34; (它来自fromto部分)

1.1.1.2将显示&#34;至&#34; (它来自to部分)

我已经想出如何将1.1.1.4写成&#34; none&#34;因为只要它显示<deny/>,我就可以将它打印为&#34; none&#34;。但我不知道如何测试它们是存在于XPath的两个部分还是仅存在于一个部分中。

我已经开始但没有工作。

XSL :(不工作)

    <xsl:apply-templates select="acl">
        <xsl:if test="from/rule/name = to/rule/name">
            <xsl:text>both</xsl:text>
        </xsl:if>
    </xsl:apply-templates>

我意识到还有其他帖子会找到复制xml并匹配它并删除两个节点完全相同。但我并没有试图删除它,而是试图报告是否有重复的节点以及它们来自何处。

2 个答案:

答案 0 :(得分:1)

这样的事情对你有用吗?

<?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" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="from" match="from/rule" use="name" />
<xsl:key name="to" match="to/rule" use="name" />

<xsl:template match="/acl">
<result>
    <group desc="from">
        <xsl:apply-templates select="from/rule[not(key('to', name))]"/>
    </group>
    <group desc="to">
        <xsl:apply-templates select="to/rule[not(key('from', name))]"/>
    </group>
    <group desc="both">
        <xsl:apply-templates select="from/rule[key('to', name)]"/>
    </group>
</result>
</xsl:template>

<xsl:template match="rule">
    <xsl:copy-of select="." />
</xsl:template>

</xsl:stylesheet>

结果:

<?xml version="1.0" encoding="utf-8"?>
<result>
<group desc="from">
<rule>
          <name>1.1.1.1</name>
          <pattern>1.1.1.1</pattern>
          <allow/>
          <log>true</log>
          <alarm>0</alarm>
        </rule>
</group>
<group desc="to">
<rule>
          <name>1.1.1.2</name>
          <pattern>1.1.1.2</pattern>
          <allow/>
          <log>true</log>
          <alarm>0</alarm>
        </rule>
</group>
<group desc="both">
<rule>
          <name>1.1.1.3</name>
          <pattern>1.1.1.3</pattern>
          <allow/>
          <log>false</log>
          <alarm>0</alarm>
        </rule>
<rule>
          <name>1.1.1.4</name>
          <pattern>1.1.1.4</pattern>
          <deny/>
          <log>true</log>
          <alarm>0</alarm>
        </rule>
</group>
</result>

编辑

与HTML输出基本相同:

<?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" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="from" match="from/rule" use="name" />
<xsl:key name="to" match="to/rule" use="name" />

<xsl:template match="/acl">
    <h3>From</h3>
    <xsl:apply-templates select="from/rule[not(key('to', name))]"/>
    <h3>To</h3>
    <xsl:apply-templates select="to/rule[not(key('from', name))]"/>
    <h3>Both</h3>
    <xsl:apply-templates select="from/rule[key('to', name)]"/>
</xsl:template>

<xsl:template match="rule">
    <p><xsl:value-of select="name" /></p>
</xsl:template>

</xsl:stylesheet>

结果:

<h3>From</h3>
<p>1.1.1.1</p>
<h3>To</h3>
<p>1.1.1.2</p>
<h3>Both</h3>
<p>1.1.1.3</p>
<p>1.1.1.4</p>

呈现为:

发件人

1.1.1.1

1.1.1.2

<强>两个

1.1.1.3

1.1.1.4

答案 1 :(得分:1)

这是另一个按原样复制文档的选项,只是在原位添加属性:

<?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" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="from" match="from/rule" use="name" />
<xsl:key name="to" match="to/rule" use="name" />

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

<xsl:template match="rule">
    <xsl:copy>
        <xsl:attribute name="group">
            <xsl:choose>
                <xsl:when test="parent::from and not(key('to', name))">
                    <xsl:text>from</xsl:text>
                </xsl:when>
                <xsl:when test="parent::to and not(key('from', name))">
                    <xsl:text>to</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>both</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

结果:

<?xml version="1.0" encoding="utf-8"?>
<acl>
  <enabled>true</enabled>
  <from>
    <rule group="from">
      <name>1.1.1.1</name>
      <pattern>1.1.1.1</pattern>
      <allow/>
      <log>true</log>
      <alarm>0</alarm>
    </rule>
    <rule group="both">
      <name>1.1.1.3</name>
      <pattern>1.1.1.3</pattern>
      <allow/>
      <log>false</log>
      <alarm>0</alarm>
    </rule>
    <rule group="both">
      <name>1.1.1.4</name>
      <pattern>1.1.1.4</pattern>
      <deny/>
      <log>true</log>
      <alarm>0</alarm>
    </rule>
    <fallthrough>
      <allow/>
      <log>true</log>
      <alarm>0</alarm>
    </fallthrough>
  </from>
  <to>
    <rule group="to">
      <name>1.1.1.2</name>
      <pattern>1.1.1.2</pattern>
      <allow/>
      <log>true</log>
      <alarm>0</alarm>
    </rule>
    <rule group="both">
      <name>1.1.1.3</name>
      <pattern>1.1.1.3</pattern>
      <allow/>
      <log>false</log>
      <alarm>0</alarm>
    </rule>
    <rule group="both">
      <name>1.1.1.4</name>
      <pattern>1.1.1.4</pattern>
      <deny/>
      <log>true</log>
      <alarm>0</alarm>
    </rule>
    <fallthrough>
      <allow/>
      <log>false</log>
      <alarm>0</alarm>
    </fallthrough>
  </to>
</acl>