XSLT - 如何使用XSLT来过滤XML文档,保持给定的元素,丢弃所有其他

问题描述:

我有这样的XML:XSLT - 如何使用XSLT来过滤XML文档,保持给定的元素,丢弃所有其他

 


    <?xml version="1.0" encoding="utf-8"?> 
    <xml> 
    <head> 
     <name>This is my XML</name> 
     <version>This is my XML</version> 
    </head> 
    <body> 
     <item id="SH2-99435"> 
      <properties> 
       <property id="69"> 
        <name>This is a property</name> 
        <amount>54.13</amount> 
        <estructure id="IZ4"> 
         <name>caterpillar</name> 
         <location><zipCode>02210</zipCode><street>South Station</street></location> 
        </estructure> 
       </property> 
       <features id="ABC3"> 
        <feature>If it works, a bug is another feature.</feature> 
        <feature>feature!!</feature> 
       </features> 
      </properties> 
      <coding> 
       <codename>Silent Hill 2</codename> 
       <developer>Team Silent</developer> 
       <publisher>Konami</publisher> 
      </coding> 
     </item> 
     <item id="SH3-4498"> 
      <text value="it has values like the other item"/> 
     </item>  
     <item id="MGS-2"> 
      <text value="it has values like the other item"/> 
     </item> 
    </body> 
    </xml> 

 

我要实现这一点:

 


    <?xml version="1.0" encoding="utf-8"?> 
    <xml> 
    <head> 
     <name>This is my XML</name> 
     <version>This is my XML</version> 
    </head> 
    <body> 
     <item> 
      <properties> 
       <property id="69"> 
        <amount>54.13</amount> 
        <estructure id="IZ4"> 
         <name>caterpillar</name> 
         <location><zipCode>02210</zipCode><street>South Station</street></location> 
        </estructure> 
       </property> 
      </properties> 
     </item> 
     <item id="SH3-4498"> 
      <text value="it should have properties and the selected sons"/> 
     </item>  
     <item id="MGS-2" > 
      <text value="it should have properties and the selected sons"/> 
     </item> 
    </body> 
    </xml> 
 

我有事像这样,正确过滤:

 


    <?xml version="1.0" encoding="utf-8"?> 
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > 

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

     <xsl:template match="xml/body/item/coding" /> 
     <xsl:template match="xml/body/item/properties/features" /> 
     <xsl:template match="xml/body/item/properties/property/name" /> 

    </xsl:stylesheet> 

 

我被告知将有10个文件通过运行生成每个人都有不同的标签;但是如果出现新标签,我们必须更改10个文件以排除不需要的标签,而不是仅在需要的文件上添加标签。例如,在另一个文件中,只有编码将被包含在内,等等。

我试着用这样的:

 
 

    <xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="some:ns"> 
     <xsl:output omit-xml-declaration="yes" indent="yes" /> 
     <xsl:strip-space elements="*" /> 
     <ns:WhiteList> 
      <name>amount</name> 
      <name>estructure</name> 
     </ns:WhiteList> 
     <xsl:template match="node()|@*"> 
      <xsl:copy> 
       <xsl:apply-templates select="node()|@*" /> 
      </xsl:copy> 
     </xsl:template> 
     <xsl:template 
      match="*[not(descendant-or-self::*[name()=document('')/*/ns:WhiteList/*])]" /> 
    </xsl:stylesheet> 
 

但它不会复制estructure的孩子。 你知道我能做什么吗?

谢谢。

更新。为此添加了理由,而不是其他方式,以及更多描述性问题。

+0

您的初始XSL看起来不够清晰!如果业务规则是复制除某些节点以外的所有内容,那就是要走的路。不过,在您的初始XSL中,它不包括** estructure **节点,但这仍然存在于您的预期输出中。 – 2012-04-20 07:46:19

+0

@TimC对不起,我已经修复了第一个包含estructure的xslt。 – StrayChild01 2012-04-20 12:15:46

我不会接受这个答案,但在回答你的直接问题时,你正在测试元素的祖先(或自我),但你忽略了其他任何东西。这意味着忽略了后代的结构。将您的xsl:if条件更改为以下内容

<xsl:if 
    test="descendant-or-self::*[generate-id(.)=$copyValue2]|ancestor::*[generate-id(.)=$copyValue2]"> 

Yuck。

老实说,你的第一个XSLT更好更干净。

如果您准确解释了您正在尝试遵循的转换规则,这可能会有所帮助。如果规则要复制除某些节点之外的所有内容,则您的第一个XSLT非常适合。如果这些规则只是复制显式节点,那么您能否详细说明究竟需要复制哪些内容,并且应该可以更好地展现一些更好的东西。

编辑:

在回应澄清,试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="some:ns"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <ns:WhiteList> 
     <name>amount</name> 
     <name>estructure</name> 
    </ns:WhiteList> 

    <xsl:variable name="whistList" select="document('')/*/ns:WhiteList" /> 

    <xsl:template match="@*"> 
     <xsl:copy/> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:if test="descendant-or-self::*[name()=$whistList/*]|ancestor::*[name()=$whistList/*]"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
     </xsl:if> 
    </xsl:template>  
</xsl:stylesheet> 

我试图用一个变量来保存文档查找整理一下了一下。请注意使用xsl的原因:如果是您不能在模板匹配中使用变量。

+0

我已更新问题以使其更清楚。我不知道它会被用作生成更多文件的过滤器,直到我被告知解决方案可能非常复杂。 – StrayChild01 2012-04-20 13:46:33

+0

非常感谢。它完美无瑕。我注意到的一件事是,它不知道如何运行速度比列出排除标签要慢。这应该是因为比较。 – StrayChild01 2012-04-20 15:19:43