Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XSLT:使用多个或';d模板匹配以应用模板_Xml_Xslt_Xpath - Fatal编程技术网

Xml XSLT:使用多个或';d模板匹配以应用模板

Xml XSLT:使用多个或';d模板匹配以应用模板,xml,xslt,xpath,Xml,Xslt,Xpath,我有一个包含多个节点的XML,每个节点中都有相似的数据。我想从每个节点中删除一个特定属性(用户:IPADDRESS)。我已经了解了如何使用ors将多个元素链接在一起,只需省去User=“{@User}”匹配,这样它就不会出现在结果中: XSL代码段: <xsl:template match="Creation | Test | Assignment | Modification | Repair | Termination"> <Creation CommitID="{@Com

我有一个包含多个节点的XML,每个节点中都有相似的数据。我想从每个节点中删除一个特定属性(用户: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语句(这是我第一次这样做的),但肯定有一种更优雅的方法,它只是在回避我。我需要处理数百万行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>

3B
2010F
1959年
2007年12月7日
c:\tests\versions\v12.txt
1.2
萨根
PC-191-NDGrasse
12345
42
2007-12-10 10:34:17
Boardset两次测试失败,未进行任何问题日志输入/修复尝试。
2001G
Cornelius将boardset升级为rev。G
XSL:


使用@DevNull解决方案的最新XSL,该解决方案将原始文件的大小增加了一倍:

<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:template match="Creation|Test|Assignment|Modification|Repair|Termination">
    <xsl:copy>
        <xsl:apply-templates select="@*[not(name()='User')]|node()"/>
    </xsl:copy>
</xsl:template>
这里还有一种方法(为了简洁起见,仅从
创建
测试中剥离)



回复评论

请改用此模板:

<xsl:template match="@User"/>
<xsl:template match="@User">
    <xsl:attribute name="User">
        <xsl:value-of select="substring-before(.,':')"/>
    </xsl:attribute>
</xsl:template>


<代码> > P> <强>我将使用我所考虑的甚至更好的解决方案:< /强>

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

注意事项

  • 我们只使用一个模板覆盖标识规则。它的身体是空的

  • 元素名称列表以管道分隔字符串的形式显示,对于长列表,这可以节省大量空间——而且,这样的字符串可以作为外部参数传递给转换,从而使其具有最大的通用性

  • 这种转变完全是“推动式”的


  • 完美的今天是我第一次使用XSLT,所以我正在努力&我知道我还有很多东西要学。我现在正在学习“XSLT For Dummies”。谢谢你的快速回答。@delliottg-到目前为止做得不错。使用标识转换,然后在需要时覆盖它,这是正确的。很多初学者直接进入
    xsl:for each
    :-)我还将添加另一个选项,您可以使用它来增加多样性。这可能是一个不同的问题,但如果我只是想从每个用户属性中去掉IP地址,该怎么办?因此User=“JRandi:192.168.1.162”将成为User=“JRandi”。Re:xsl:for each,我昨天和今天花了很多时间阅读Dimitre Novatchev和Tomalak等人的答案,并了解到这不是一个好办法。@delliottg-遵循这两位专家的建议是不会出错的。我添加了一个更新,以涵盖从
    用户
    属性中剥离IP。我使用上面的答案XSL对我的一个较大文件(140mb)运行转换,结果文件的大小略微增加了一倍(283mb)。我认为它可能只是将结果附加到第一次转换的结果中,但事实并非如此,我也看不出文件变得如此大的任何简单原因(它不会在Notepad++中打开,我必须在gVIM中打开才能查看)。有什么想法吗?好问题,+1。您可能对一个稍好一点的解决方案感兴趣,该解决方案比较短,并且适用于无限长的元素名称列表,甚至可以将其作为参数传递给转换。谢谢您的解决方案。我有几个问题,我正在一个相当大的文件(140mb)上运行这个程序,它已经运行了10多分钟了(不确定我是什么时候开始的),DevNull的解决方案在不到一分钟的时间内运行。我可以看到您的解决方案仍在处理中,因为我可以看到生成文件的文件大小在增长,但这需要很长时间。你知道为什么时差这么大吗?另一种转换也有问题,请参阅我对该转换的评论。@delliottg,两种解决方案的效率应该大致相同。我感觉您正在尝试将这些解决方案调整为不同的XML格式,很可能您没有以正确的方式进行调整。建议提供一个完全具有代表性(但很小)的源XML文档和确切的所需结果——这样我们就能够给出一个不需要修改的解决方案。我试图通过对数据、jig名称等进行一些模糊处理,并以每种类型的“CommitID”为例,对文件进行严重截断在示例文件中。我提供的示例的格式非常接近实际数据(由于公司限制,我无法提供),但是我不能否认数据中可能有我不知道的东西(只在这里呆了4周),而且文件很大。我将花一些时间构建一个更完整的XML示例&将其附加到原始问题中。谢谢你的帮助,我很感激。
    <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>
    
    <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>