16

それぞれに同様のデータを持つ複数のノードを持つ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ステートメントを使用してブルートフォース攻撃を実行できることは知っていますが(これが初めての方法です)、より洗練された方法が必要であり、それは私を回避しているだけです。処理するXMLの行は数百万行あり、これは私が行わなければならない多くの変換の最初のものにすぎません。

Win7ボックスでmsxslV4.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>

元のファイルのサイズを2倍にする@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: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>
4

2 に答える 2

20

テンプレートを次のように変更してみてください。

<xsl:template match="Creation|Test|Assignment|Modification|Repair|Termination">
    <xsl:copy>
        <xsl:apply-templates select="@*[not(name()='User')]|node()"/>
    </xsl:copy>
</xsl:template>

に述語が追加されたIDテンプレートによく似ていることに気付くでしょう@*

Userまた、要素が何であるかに関係なくすべての属性を削除したい場合は、代わりにこのテンプレートを使用できます。

<xsl:template match="@User"/>

もう1つの方法があります(簡潔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>
于 2012-11-09T23:03:38.540 に答える
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>

注意してください:

  1. アイデンティティ ルールをオーバーライドする 1 つのテンプレートのみを使用します。その体は空です。

  2. 要素名のリストは、パイプで区切られた文字列として表示され、長いリストの場合、これによりスペースが大幅に節約されます。また、このような文字列は外部パラメーターとして変換に渡すことができるため、最大の汎用性があります。

  3. 今回の変身は完全に「押しスタイル」。

于 2012-11-10T16:09:11.323 に答える