XML-XSLT-使用两个XML输入文档

时间:2018-07-12 18:08:11

标签: xml xslt xslt-3.0

我有一个可能很容易解决的小问题,但是整个下午我都忙着解决,我真的不知道如何解决它,

基本上,我有以下输入XML文档:

<?xml version="1.0" encoding="UTF-8"?>
<parent>
    <childs>
        <child ID="1" name="John" />
        <child ID="2" name="Marie"/>
        <child ID="3" name="Joseph"/>
    </childs>
</parent> 

我想向其中添加另一个<child>元素,但是我想从一个名为'inputStack.xml'的外部文件中获得孩子的名字,

<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design">
    <property name="units">in</property>
    <text-property name="displayName">Daisy</text-property>
    <text-property name="text">Just plain text</text-property>
</report>

基本上我想添加一个名为Daisy的新<child>元素

这是我想要获取的输出XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<parent>
    <childs>
        <child ID="1" name="John"/>
        <child ID="2" name="Marie"/>
        <child ID="3" name="Joseph"/>
        <child ID="4" name="Daisy"/>
    </childs>
</parent>

这是我正在使用的XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  expand-text="yes"
  version="3.0">

    <xsl:output indent="yes" />

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:template match="parent/childs/child[last()]">

    <xsl:next-match/>
        <child>
            <xsl:attribute name="ID">
                <xsl:value-of select="count(preceding-sibling::child)+2" />
            </xsl:attribute>
            <xsl:attribute name="name">
                <xsl:value-of select="document('inputStack.xml')/report/text-property[@name = 'displayName']"/>
            </xsl:attribute>

        </child>
    </xsl:template>

</xsl:stylesheet>

我得到的输出是这样:

<?xml version="1.0" encoding="UTF-8"?>
<parent>
    <childs>
        <child ID="1" name="John"/>
        <child ID="2" name="Marie"/>
        <child ID="3" name="Joseph"/>
        <child ID="4" name=""/>
    </childs>
</parent>

如您所见,我无法在属性text-property等于name的{​​{1}}元素中获取值...

现在这是我遇到的问题:如您所见,我正在使用的外部文件/文档具有值为displayName的{​​{1}}属性。我发现如果删除此属性,则XSLT代码将起作用,并且将值xmlns添加到生成的XML文档中。但是问题是我无法从外部XML文件中删除该属性,那么如何为该外部文档定义一个名称空间以使其起作用?还是有其他方法可以做到这一点?

谢谢!

编辑/更新

我正在尝试在http://www.eclipse.org/birt/2005/design函数中使用Daisy函数,但是我不知道为什么它不起作用...所以我正在使用的外部文件已更新:< / p>

document()

这是我的XSLT更新:

count()

这是我得到的结果:

<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design">
    <property name="units">in</property>
    <text-property name="displayName">Daisy</text-property>
    <text-property name="text">Just plain text</text-property>
    <propList>
        <prop name="prop1"/>
        <prop name="prop2"/>
        <prop name="prop3"/>
        <prop name="prop4"/>
        <prop name="prop5"/>
    </propList>
</report>

所以<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ecd="http://www.eclipse.org/birt/2005/design" exclude-result-prefixes="xs ecd" expand-text="yes" version="3.0"> <xsl:output indent="yes" /> <xsl:mode on-no-match="shallow-copy"/> <xsl:template match="parent/childs/child[last()]"> <xsl:next-match/> <child> <xsl:attribute name="ID"> <xsl:value-of select="count(preceding-sibling::child)+2" /> </xsl:attribute> <xsl:attribute name="name"> <xsl:value-of select="document('inputStack.xml')/ecd:report/ecd:text-property[@name = 'displayName']"/> </xsl:attribute> <!--new attribute--> <xsl:attribute name="nProps"> <xsl:value-of select="count(document('inputStack.xml')/ecd:report/ecd:propList/(preceding-sibling::ecd:prop[last()]))+1"/> </xsl:attribute> </child> </xsl:template> </xsl:stylesheet> 的值应该是5而不是1 ...我在路径中做错了吗?谢谢

Alexandre Jacinto

2 个答案:

答案 0 :(得分:3)

对于该单个指令,您可以使用

<xsl:value-of xpath-default-namespace="http://www.eclipse.org/birt/2005/design" select="document('inputStack.xml')/report/text-property[@name = 'displayName']"/>

请参见https://www.w3.org/TR/xslt-30/#unprefixed-qnames。如果在需要使用命名空间的地方有更多XSLT元素,则可以在公共容器元素上声明xpath-default-namespace,但请记住要使用具有不同命名空间的两个文档,因此需要确保使用这些元素您需要默认名称空间为空的位置时,不要覆盖它。

根据您的需求,在样式表中使用<xsl:stylesheet xmlns:ecd="http://www.eclipse.org/birt/2005/design" ...>声明名称空间的前缀,然后在需要时使用该前缀来限定XPath表达式中的元素名称document('inputStack.xml')/ecd:report/ecd:text-property[@name = 'displayName']可能会更容易。 / p>

答案 1 :(得分:0)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs mn"  xmlns:mn="http://www.eclipse.org/birt/2005/design"
    version="2.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:variable name="doc" select="document('date3.xml')"/>
    <xsl:template match="parent">
        <xsl:copy>
            <childs>
                <xsl:for-each select="childs/child">
                <child>
                   <xsl:attribute name="ID">
                       <xsl:value-of select="@ID"/>
                   </xsl:attribute>
                    <xsl:attribute name="name">
                        <xsl:value-of select="@name"/>
                    </xsl:attribute>
                </child>
                </xsl:for-each>
                <child>
                    <xsl:attribute name="ID">
                        <xsl:value-of select="'4'"/>
                    </xsl:attribute>
                    <xsl:attribute name="name">
                        <xsl:value-of select="$doc/mn:report/mn:text-property[@name='displayName']"/>
                    </xsl:attribute> 
                </child>
            </childs>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>