简体   繁体   English

xslt - 如何使用xslt过滤XML文档,保留给定元素,丢弃所有其他元素

[英]xslt - How to filter a XML document using xslt, keep given elements, discard all others

I have this xml: 我有这个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>

And I want to achieve this: 我想实现这个目标:



    <?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>
    

I have something like this, which filters correctly: 我有这样的东西,它正确过滤:



    <?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>

I have been told that there are going to be 10 files being produced by running this filter, each one with different tags; 我被告知通过运行此过滤器将生成10个文件,每个文件都有不同的标签; but if a new tag comes, we would have to change 10 files to exclude the unwanted tag, instead of only add a tag on the file that is needed. 但是如果出现新标签,我们将不得不更改10个文件以排除不需要的标签,而不是仅在需要的文件上添加标签。 For example, on the other file, only coding is going to be included, and so on. 例如,在另一个文件中,仅包括编码,依此类推。

I tried with this: 我试过这个:

    

    <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>
    

But it doesn't copy the children of estructure. 但它并没有复制estructure的孩子们。 Do you know what I could do? 你知道我能做什么吗?

Thanks. 谢谢。

Update. 更新。 Added justification to make it this way and not the other way around, and more descriptive question. 添加理由以这种方式而不是相反的方式,以及更具描述性的问题。

I wouldn't accept this answer, but in answer to your immediate question, you are testing for elements which are ancestors (or self) of the estructure element, but you ignore anything else. 我不接受这个答案,但是在回答你的直接问题时,你正在测试作为estructure元素的祖先(或自我)的元素,但你忽略了其他任何东西。 This means descendants of the estructure are ignored. 这意味着忽略了estructure的后代。 Change your xsl:if condition to the following 将xsl:if条件更改为以下内容

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

Yuck. 呸。

Honestly, your first XSLT is much nicer and cleaner. 老实说,你的第一个XSLT更好,更清洁。

It would probably help if you explained exactly what the rules are you are trying to follow with the transformation. 如果你准确地解释了你试图遵循转换的规则,那可能会有所帮助。 If the rules are to copy everything except certain nodes, then your first XSLT is ideal for that. 如果规则要复制某些节点之外的所有内容,那么您的第一个XSLT就是理想的选择。 If the rules are copy only explicit nodes, then could you give a bit more detail as to what exactly needs to be copied, and it should be possible to rustle up something much nicer. 如果规则只复制显式节点,那么你能否提供一些关于究竟需要复制的更多细节,并且应该可以更好地挖掘更好的东西。

EDIT: 编辑:

In response to the clarification, try this 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>

I have tried to tidy it up a bit by using a variable to hold the document look-up. 我试图通过使用变量来保持文档查找来整理它。 Note the reason for using the xsl:if is that you can't use variables in the template match. 注意使用xsl的原因:if是你不能在模板匹配中使用变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM