我有一个包含多个节点的XML,每个节点都有类似的数据。我想从每个节点删除一个特定的属性(USER:IPADDRESS)。我已经想出如何使用ors链接一些元素,只是省略了User =“{@ User}”匹配,因此它不会显示在结果中:
XSL片段:
<xsl:template match="Creation | Test | Assignment | Modification | Repair | Termination">
<Creation CommitID="{@CommitID}" Date="{@Date}" BoardID="{@BoardID}">
<xsl:apply-templates/>
</Creation>
</xsl:template>
不出所料,“Creation”之后的所有节点名称都被重新命名为Creation,因为这就是我告诉它要做的事情。如何传递各种匹配,以便在结果中以正确的顺序应用它们?我知道我可以使用相同的XSL语句为各种匹配(这是我第一次这样做)的蛮力方式,但必须有一个更优雅的方法,它只是回避我。我有数百万&amp;要处理数百万行XML,这只是我必须进行的许多转换中的第一步。
我在Win7盒子上使用msxsl V4.0进行转换,如果有任何后果的话。
XML:
<?xml version="1.0"?>
<BoardDatabase>
<Board_Data BoardID="1035">
<Creation CommitID="12b" Date="2007-12-07T15:43:51" BoardID="1035" User="CSAGAN:192.168.1.177">
<BoardDrawing>3B</BoardDrawing>
<AssemblyDrawing>2010F</AssemblyDrawing>
<Notes>PO Num 1959</Notes>
</Creation>
<Test CommitID="117" Date="2007-12-10T10:39:43" BoardID="1035" User="CSAGAN:192.168.1.183">
<ElectricalTestData Result="FAIL" Version="IMM STD REVF">
<AutomatedTest ReportVersion="1.0">
<TestSetup>
<TestAppBuildDate>Dec 07 2007</TestAppBuildDate>
<VersionPath>c:\tests\versions\v12.txt</VersionPath>
<VersionNumber>1.2</VersionNumber>
<OperatorName>CSAGAN</OperatorName>
<StationID>PC-191-NDGrasse</StationID>
<JigSN>12345</JigSN>
<JigAssembly>42</JigAssembly>
<TestStartTime>2007-12-10 10:34:17</TestStartTime>
</TestSetup>
</AutomatedTest>
</ElectricalTestData>
</Test>
<Assignment CommitID="1c1f" User="JRandi:192.168.1.162" Date="2008-09-30T07:36:52" BoardID="1035">
<Notes>Boardset failed etest twice, no problem log entry/repair attempts made.</Notes>
</Assignment>
<Modification CommitID="2bb7" User="JRandi:192.168.1.162" Date="2009-03-11T13:31:21" BoardID="1035">
<AssemblyDrawing>2001G</AssemblyDrawing>
<Notes>Cornelius upgraded boardset to rev. G</Notes>
</Modification>
</Board_Data>
</BoardDatabase>
XSL:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="Creation | Test | Assignment | Modification | Repair | Termination">
<Creation CommitID="{@CommitID}" Date="{@Date}" BoardID="{@BoardID}">
<xsl:apply-templates/>
</Creation>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
最新的XSL使用@ DevNull的解决方案,使原始文件的大小加倍:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Answer from Stack Overflow that only strips out the IP Address from the User attribute. -->
<xsl:template match="@User">
<xsl:attribute name="User">
<xsl:value-of select="substring-before(.,':')"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
来自@ Dimitre解决方案的最新XSL需要很长时间才能处理(超过30分钟后仍在运行,但文件仍在增长):
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[contains('|Creation|Test|Assignment|Modification|Repair|Termination|',concat('|', name(), '|'))
]/@user"/>
</xsl:stylesheet>
答案 0 :(得分:17)
尝试将模板更改为:
<xsl:template match="Creation|Test|Assignment|Modification|Repair|Termination">
<xsl:copy>
<xsl:apply-templates select="@*[not(name()='User')]|node()"/>
</xsl:copy>
</xsl:template>
你会发现它看起来很像你的身份模板,谓词已添加到@*
。
此外,如果您想要删除所有User
属性,无论元素是什么,您都可以使用此模板:
<xsl:template match="@User"/>
这是另一种方式(仅为了简洁而从Creation
和Test
剥离)
<xsl:template match="@User[..[self::Creation or self::Test]]"/>
回答评论
请改用此模板:
<xsl:template match="@User">
<xsl:attribute name="User">
<xsl:value-of select="substring-before(.,':')"/>
</xsl:attribute>
</xsl:template>
答案 1 :(得分:2)
我会使用我认为更好的解决方案:
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[contains('|Creation|Test|Assignment|Modification|Repair|Termination|',
concat('|', name(), '|'))
]/@user"/>
</xsl:stylesheet>
请注意:
我们只使用一个模板覆盖身份规则。它的身体是空的。
元素名称列表以管道分隔的字符串表示,对于长列表,这可以节省大量空间 - 此外,这样的字符串可以作为外部参数传递给转换,从而使其最大化
这种转变完全是“推动式”。