XSLT 사용, 두 번째 XML 문서의 내용을 기반으로 하나의 XML 문서를 변환합니다.

StackOverflow https://stackoverflow.com/questions/647324

  •  22-07-2019
  •  | 
  •  

문제

세 번째 문서 세트로 변환 해야하는 두 번째 객체 세트에 대한 허용 된 필드를 암시 적으로 정의하는 문서 세트가 있습니다 (사용해야 할 "규칙"문서가 변환되는 파일의 내용에 따라 다름)

<!-- 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를 사용 하여이 변환을 수행 할 수 있습니까?

내가 볼 "XSLT에는 XPATH 표현식 (예 : 변수 참조)을 런타임에 구축하는 방법이 없습니다." 그래서 운이 좋지 않거나이 문제를 잘못보고 있습니까? 감사!

도움이 되었습니까?

해결책

간단한 솔루션이 있습니다:

이 변형:

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

메모 "규칙 문서"는 구성을 위해 스타일 시트 내에 있습니다. 별도의 문서 인 경우 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 스타일 시트가되었습니다. 그런 다음이 결과 스타일 시트를 소스 문서에 적용하면 기대하는 결과를 얻을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top