xsltを使用して、2番目のxmlドキュメントの内容に基づいて1つのxmlドキュメントを変換します
質問
ドキュメントの3番目のセットに変換する必要があるオブジェクトの2番目のセットの許可フィールドを暗黙的に定義するドキュメントの1つのセットがあります( どの「ルール」使用するドキュメントは、変換されるファイルのコンテンツに依存します)
<!-- One example rules document -->
<document object="obj1_rules">
<field name="A"/>
<field name="B"/>
<field name="C"/>
</document>
<!-- Document to be tranformed based upon obj1_rules-->
<document object="obj1">
<field name="A"/>
<field name="B"/>
<field name="C"/>
<field name="D"/>
<field name="E"/>
</document>
<!-- Desired result-->
<document object="obj1">
<newfield name="A"/>
<newfield name="B"/>
<newfield name="C"/>
</document>
xsltを使用してこの変換を行うことは可能ですか?
&quot; XPath式を構築するXSLTには方法がない(たとえば、変数参照)実行時に。&quot; それで私は運が悪いのですか、それともこの問題を間違って見ているだけですか?ありがとう!
解決
簡単な解決策は次のとおりです:
この変換:
<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:variable name="vrtfRules">
<document object="obj1_rules">
<field name="A"/>
<field name="B"/>
<field name="C"/>
</document>
</xsl:variable>
<!-- -->
<xsl:variable name="vRules" select=
"document('')/*/xsl:variable
[@name = 'vrtfRules']
/*
"/>
<!-- -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- -->
<xsl:template match="field">
<xsl:if test="@name = $vRules/*/@name">
<newfield>
<xsl:apply-templates select="node()|@*"/>
</newfield>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
元から提供されたソースXMLドキュメントに適用される場合:
<document object="obj1">
<field name="A"/>
<field name="B"/>
<field name="C"/>
<field name="D"/>
<field name="E"/>
</document>
目的の結果を生成します:
<document object="obj1">
<newfield name="A"/>
<newfield name="B"/>
<newfield name="C"/>
</document>
注&quot;ルールドキュメント&quot;コンパクトにするためにスタイルシート内にあります。別のドキュメントの場合は、 document()
関数は、実際の href
で調整する必要があります。
他のヒント
たぶん私は単純化しすぎていますが、「ルール文書」という理由があります。単純にXSLTにすることはできませんか?
まあ、なぜ本格的なxslスタイルシートではなく単純なxmlファイルにルールを入れたいのかわかりますが、単にステップをスキップしているだけです。
xmlルールドキュメントをxslスタイルシートに変換してからソースxmlに適用するxslスタイルシートを作成する必要があります。
トリックは名前空間にあり、適用されるxslルールと生成されるxslルールの混同によって混乱しないようにします。
<?xml version="1.0" ?> <xsl:stylesheet xmlns="YOUR_NAMESPACE_HERE" xmlns:output="http://www.w3.org/1999/XSL/Transform" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="xml" indent="yes" media-type="text/xsl" /> <xsl:template match="/"> <output:stylesheet version="2.0"> <xsl:apply-templates /> </output:stylesheet> </xsl:template> <xsl:template match="document[@object]"> <output:template match="document[@object='{@object}']"> <output:copy> <xsl:apply-templates /> </output:copy> </output:template> </xsl:template> <xsl:template match="field[@name]"> <output:if test="field[@name='{@name}']"> <output:copy-of select="field[@name='{@name}']" /> </output:if> </xsl:template> </xsl:stylesheet>
ルールとドキュメント自体で同じドキュメントオブジェクト属性を使用すると仮定しました(これははるかに単純なimoです)。
したがって、上記のスタイルシートを使用してルール文書を実行します。結果は、XMLルールドキュメントで記述したとおりのことを行う新しいxslスタイルシートです。次に、この結果のスタイルシートをソースドキュメントに適用すると、期待どおりの結果が得られます。