1

私の(簡略化された)入力 XML ファイルには、次のものが含まれています。

<?xml version="1.0" encoding="UTF-8"?>
<main>
    <DATA_RECORD>
        <MESSAGE>&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;</MESSAGE>
    </DATA_RECORD>
</main>

MESSAGE 要素の値は、文字エスケープされた XML インスタンスです。次の XML を表します。

<pd>
    <cdhead version="13"/>
</pd>

入力 XML に xsl 変換を適用し、何らかの方法で MESSAGE コンテンツを変数に解析し、Xpath 式を使用してその詳細にアクセスしたいと考えています。
以下のように JavaScript 関数を追加しようとしましたが、スクリプトによって返されたオブジェクトは明らかに間違った DOM サブクラスです (下の結果を参照)。完全を期すために、DOM の内容を文字列として返す関数を追加しました。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:my="http://example.com/my"
    exclude-result-prefixes="ms my">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <ms:script language="JScript" implements-prefix="my">
        <![CDATA[
        function parseToDOM (input) {
        var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
        doc.loadXML (input);
        return doc.documentElement;
        };
        function parseToXMLString (input) {
        var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
        doc.loadXML (input);
        return doc.documentElement.xml;
        };
        ]]>
    </ms:script>

    <xsl:template match="/">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>

    <xsl:template match="DATA_RECORD">
            <xsl:variable name="DOM"><xsl:copy-of select="my:parseToDOM (MESSAGE)"/></xsl:variable>
            <xsl:variable name="XML"><xsl:copy-of select="my:parseToXMLString (MESSAGE)"/></xsl:variable>

            <msg1><xsl:value-of select="$XML"/></msg1>
            <msg2><xsl:value-of select="$XML" disable-output-escaping="yes"/></msg2>
            <dom><xsl:copy-of select="$DOM"/></dom>
            <version><xsl:value-of select="$DOM/pd/cdhead/@version"/></version>
    </xsl:template>

    <xsl:template match="text()"/>
</xsl:stylesheet>

結果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <msg1>&lt;pd&gt;
    &lt;cdhead version="13"/&gt;
&lt;/pd&gt;</msg1>
    <msg2><pd>
    <cdhead version="13"/>
</pd></msg2>
    <dom/>
    <version></version>
</root>

Jscript 関数が Xpath を使用できる結果を返すようにするにはどうすればよいですか?
ところで、エスケープされた XML 文字列を解析して Xpath を使用できる結果にする XSLT 1.0 関数はありますか?

添加

私はいくつかのバリエーションを試しており、解決策に近づいています。まず、Altova XMLSpy では xsl プロセッサーを選択でき、組み込みのものを使用すると上記の結果になりました。もちろん、MSXML 6.0 が必要ですが、それを選択すると、代わりに input.text を解析する必要があったため、エラーが発生しました。しかし、JavaScriptで余分なことをした後、結果でXpath式を使用できるようになっただけです。while&#60;などは etcetera に解析されますが&lt;、これだけでは適切な DOM の結果に到達できないことが判明しました。そのため、最初に入力文字列のエスケープを解除することにしました。
しかし、私は別の障害にぶつかりました。以下は正常に機能しますが、以下input.textのリテラルの代わりに使用すると機能しません。

以下の xslt を参照してください。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:my="http://example.com/my"
    exclude-result-prefixes="ms my">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <ms:script language="JScript" implements-prefix="my">
        <![CDATA[
        function parseToDOM (input) {
            var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
            doc.loadXML (unescapeXML ('&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;'));
            //doc.loadXML (unescapeXML (input.text));
            return doc;
        };
        function unescapeXML (str) {
            var ostr = str;
            ostr = ostr.replace (/&#34;/g, '"');
            ostr = ostr.replace (/&#60;/g, '<');
            ostr = ostr.replace (/&#61;/g, '=');
            ostr = ostr.replace (/&#62;/g, '>');
            return ostr;
        };
        ]]>
    </ms:script>

    <xsl:template match="/">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>

    <xsl:template match="DATA_RECORD">
        <xsl:variable name="msg" select="my:parseToDOM (MESSAGE)"/>
        <tst><xsl:value-of select="$msg/pd/cdhead/@version"/></tst>
   </xsl:template>

</xsl:stylesheet>

今の結果

<?xml version="1.0" encoding="UTF-8"?>
<root>
<tst>13</tst>
</root>

これはまさに私が欲しいものです。

しかし、上で述べたように、リテラルの解析についてコメントし、代わりに入力を使用すると、次のようになります。

//doc.loadXML (unescapeXML ('&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;'));
doc.loadXML (unescapeXML (input.text));

次のエラーが表示されます (xslt パーサーとして MSXML 6.0 を使用する Altova XML Spy で):

XSL transformation failed due to following error:

Microsoft JScript runtime error
'undefined' is null or not an object
line = 10, col = 3 (line is offset from the start of the script block).
Error returned from property or method call.

最初の JavaScript の replace ステートメントを指します。

また、IE9 は以下を適切に処理できません。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xslt"?>
<main>
  <DATA_RECORD>
    <MESSAGE>&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;</MESSAGE>
  </DATA_RECORD>
 </main>

このファイルを IE9 で開くと (ここで、test.xslt は入力が無視され、代わりにリテラルが処理される変換のバージョンであるため、XML Spy では問題ありません)、処理エラーが発生します。

XML5001: Applying Integrated XSLT Handling. 
XSLT8690: XSLT processing failed. 

これはなぜですか?どうすれば修正できますか?

4

1 に答える 1

2

上記のADDITIONから始めて、少し微調整することで解決策にたどり着きました。代わりにプレーンを使用
する必要を避けるために、xsl には xslt文字列関数を適用して要素を文字列に変換する必要があります (既に文字列だと思っていましたが、そうではないようです)。さらに、replace ステートメントを適用する必要がなくなりました。 したがってinput.textinput

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:my="http://example.com/my"
    exclude-result-prefixes="ms my">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <ms:script language="JScript" implements-prefix="my">
        <![CDATA[
        function parseToDOM (input) {
            var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
            doc.loadXML (input);
            return doc;
        };
        ]]>
    </ms:script>

    <xsl:template match="/">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>

    <xsl:template match="DATA_RECORD">
        <xsl:variable name="msg" select="my:parseToDOM (string(MESSAGE))"/>
        <tst><xsl:value-of select="$msg/pd/cdhead/@version"/></tst>
   </xsl:template>

</xsl:stylesheet>

作品:適用時

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xslt"?>
<main>
  <DATA_RECORD>
    <MESSAGE>&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;</MESSAGE>
  </DATA_RECORD>
 </main>

結果は

<?xml version="1.0" encoding="UTF-8"?>
<root>
<tst>13</tst>
</root>

残念ながら、IE9 は、参照された XSLT を含む XML の読み込みにまだ失敗しています。そして私はその理由を発見しました。
Internet Options/Advanced/Security/Allow active content to run in files on My Computer のボックスにチェックを入れ、IE を再起動する必要がありました。これにより、IE9 でファイルが正しく処理されます。もちろん結果がhtmlにならないということはF12/Scriptタブでしか結果を見ることができないということですが、これは一例であり、適切なhtmlを生成するxsltに組み込んでいきます。

于 2013-02-18T11:55:44.987 に答える