Bash 在xmllint验证后删除无效的XML

Bash 在xmllint验证后删除无效的XML,bash,validation,scripting,xsd,xmllint,Bash,Validation,Scripting,Xsd,Xmllint,我收到一个大的XML文件,并且XML文件通常不会验证为模式文件。 我希望删除“无效”内容并保存xml文件的其余部分,而不是删除整个xml文件 我使用xmllint通过以下命令验证xml: xmllint -schema testSchedule.xsd testXML.xml XSD文件(在本例中名为testSchedule.XSD): 这一切都是正确的——XML文件中有两个错误 现在,我想使用某种工具来删除条目3和条目4,因此我得出以下结果: <?xml version="1.0" e

我收到一个大的XML文件,并且XML文件通常不会验证为模式文件。 我希望删除“无效”内容并保存xml文件的其余部分,而不是删除整个xml文件

我使用xmllint通过以下命令验证xml:

xmllint -schema testSchedule.xsd testXML.xml
XSD文件(在本例中名为testSchedule.XSD):

这一切都是正确的——XML文件中有两个错误

现在,我想使用某种工具来删除条目3和条目4,因此我得出以下结果:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<MasterData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.testing.dk">
    <Items>
        <Item>
            <Id>1</Id>
            <Width>10</Width>
            <Height>100</Height>
            <Remark>This is OK</Remark>
        </Item>
        <Item>
            <Id>2</Id>
            <Width>20</Width>
            <Height>200</Height>
            <Remark>This is OK - But is missing Height a non mandatory field</Remark>
        </Item>
        <Item>
            <Id>5</Id>
            <Width>50</Width>
            <Height>500</Height>
            <Remark>This is OK and the last</Remark>
        </Item>
    </Items>
</MasterData>

1.
10
100
这没关系
2.
20
200
这是可以的-但是缺少高度是非必填字段吗
5.
50
500
这是最后一次
这里有没有人有能做到这一点的工具? 我目前正在使用bash脚本和xmllint。
我真的希望有人能帮上忙。

通过这个XSLT样式表,您可以在任何支持XSLT 1.0(大多数语言)的环境中运行,使用命令行工具,如
xsltproc
libxslt
)或Saxon、浏览器或在线工具。这里有一个例子

如果使用以下样式表将原始XML文件作为输入提供给XSLT转换器,它将生成在第二个XML中显示的结果:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:t="http://www.testing.dk">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="t:Item[t:Id     and not(number(t:Id))]"/>
    <xsl:template match="t:Item[t:Width  and not(number(t:Width))]"/>
    <xsl:template match="t:Item[t:Height and not(number(t:Height))]"/>
    <xsl:template match="t:Item[not(t:Width)]"/>
    <xsl:template match="t:Item[not(t:Id)]"/>
    <xsl:template match="t:Item[not(t:Remark)]"/>

</xsl:stylesheet>

您可以使用XSLT。XSLT允许您转换格式良好的XML文档(即使无效)。在您的问题中添加XSLT标记,您应该会得到一些建议。感谢您的快速帮助。所述文件是包含少量数据和错误的测试文件。我收到的XML文件很大!!模式超过3000行。在我看来,XSLT解决方案可以处理众所周知的错误,但每次我都会遇到很多不同的验证错误——这是由于数据损坏造成的——因此我很难让XSLT解决这个问题。实际上,我发布了一个简单的XSLT 1.0兼容示例,因为您可以很容易地在您的环境中找到它。但是,您仍然可以考虑XSLT 2,因为您的任务是转换XML文档。XSLT2.0具有支持模式的特性,可以自动处理比我在这里介绍的更多的内容。看见添加一个XSLT标记或提出一个新问题,询问XSLT2.0解决方案,并提及这些要求。你应该得到一些你可能会用到的有趣的解决方案。
testXML.xml:18: element Height: Schemas validity error : Element '{http://www.testing.dk}Height': This element is not expected. Expected is ( {http://www.testing.dk}Width ).
testXML.xml:23: element Width: Schemas validity error : Element '{http://www.testing.dk}Width': 'TheIsAString' is not a valid value of the atomic type 'xs:integer'.
testXML.xml fails to validate
<?xml version="1.0" encoding="ISO-8859-1" ?>
<MasterData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.testing.dk">
    <Items>
        <Item>
            <Id>1</Id>
            <Width>10</Width>
            <Height>100</Height>
            <Remark>This is OK</Remark>
        </Item>
        <Item>
            <Id>2</Id>
            <Width>20</Width>
            <Height>200</Height>
            <Remark>This is OK - But is missing Height a non mandatory field</Remark>
        </Item>
        <Item>
            <Id>5</Id>
            <Width>50</Width>
            <Height>500</Height>
            <Remark>This is OK and the last</Remark>
        </Item>
    </Items>
</MasterData>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:t="http://www.testing.dk">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="t:Item[t:Id     and not(number(t:Id))]"/>
    <xsl:template match="t:Item[t:Width  and not(number(t:Width))]"/>
    <xsl:template match="t:Item[t:Height and not(number(t:Height))]"/>
    <xsl:template match="t:Item[not(t:Width)]"/>
    <xsl:template match="t:Item[not(t:Id)]"/>
    <xsl:template match="t:Item[not(t:Remark)]"/>

</xsl:stylesheet>
xsltproc stylesheet.xsl testXML.xml > fixedXML.xml