xslt - 根据父属性修改文本子项
xslt - modify text child based on father attribute
所以,mi 问题看起来很简单,但我被卡住了。我想根据 id 属性在 xml 中填充文本元素,我的 xml 是一个如下所示的 PageXML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PcGts xmlns="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15 http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15/pagecontent.xsd">
<Metadata>
<Creator>myself</Creator>
<Created>2021-07-03T09:37:54.369908+00:00</Created>
<LastChange>2021-07-03T09:37:54.369944+00:00</LastChange>
</Metadata>
<Page imageFilename="05.tif" imageWidth="3243" imageHeight="4077">
<TextRegion id="eSc_dummyblock_">
<TextLine id="eSc_line_b74d9f71" >
<Coords points="1376,108 1390,67 1492,78 1492,166 1431,149 1407,166 1390,149 1376,156"/>
<Baseline points="1380,112 1499,112"/>
<TextEquiv>
<Unicode></Unicode>
</TextEquiv>
</TextLine>
<TextLine id="eSc_line_5aceacfb" >
<Coords points="2882,173 2882,142 2947,125 2947,292 2920,288 2882,309"/>
<Baseline points="2886,176 2954,176"/>
<TextEquiv>
<Unicode>toto</Unicode>
</TextEquiv>
</TextLine>
</TextRegion>
</Page>
</PcGts>
我只想传递一个 xslt 模板,以便根据 TextLine id 属性用不同的值填充每个 Unicode 元素。像这样的东西必须工作,但是,没有任何反应。
import lxml.etree as ET
dom = ET.parse(filename)
xslt_root = etree.XML(
'''<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@id[. = 'eSc_line_b74d9f71']/*/Unicode/text()[. = '']">something else</xsl:template>
</xsl:stylesheet>''')
transform = ET.XSLT(xslt_root)
newdom = transform(dom)
期望的输出:
<?xml version="1.0" encoding="UTF-8"?>
<TextRegion id="eSc_dummyblock_">
<TextLine id="eSc_line_b74d9f71">
<Coords points="1376,108 1390,67 1492,78 1492,166 1431,149 1407,166 1390,149 1376,156"/>
<Baseline points="1380,112 1499,112"/>
<TextEquiv>
<Unicode>something else</Unicode>
</TextEquiv>
</TextLine>
<TextLine id="eSc_line_5aceacfb">
<Coords points="2882,173 2882,142 2947,125 2947,292 2920,288 2882,309"/>
<Baseline points="2886,176 2954,176"/>
<TextEquiv>
<Unicode/>
</TextEquiv>
</TextLine>
</TextRegion>
我会感谢你的帮助
----解决方案---
正如@michael.hor257k 所建议的那样,解决方案是在 xslt 样式表中声明相同的名称空间:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:met="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15"
exclude-result-prefixes="met">
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="met:TextLine[@id='eSc_line_b74d9f71']/met:TextEquiv/met:Unicode">
<xsl:copy>something else</xsl:copy>
</xsl:template>
</xsl:stylesheet>
换行怎么样
<xsl:template match="@id[. = 'eSc_line_b74d9f71']/*/Unicode/text()[. = '']">something else</xsl:template>
到
<xsl:template match="*[@id = 'eSc_line_b74d9f71']/TextEquiv/Unicode"><Unicode>something else</Unicode></xsl:template>
或者更通用的版本
<xsl:template match="*[@id = 'eSc_line_b74d9f71']/TextEquiv/Unicode"><xsl:copy>something else</xsl:copy></xsl:template>
根据您的输入,这将为您提供输出
<?xml version="1.0" encoding="UTF-8"?>
<TextRegion id="eSc_dummyblock_">
<TextLine id="eSc_line_b74d9f71">
<Coords points="1376,108 1390,67 1492,78 1492,166 1431,149 1407,166 1390,149 1376,156"/>
<Baseline points="1380,112 1499,112"/>
<TextEquiv>
<Unicode>something else</Unicode>
</TextEquiv>
</TextLine>
<TextLine id="eSc_line_5aceacfb">
<Coords points="2882,173 2882,142 2947,125 2947,292 2920,288 2882,309"/>
<Baseline points="2886,176 2954,176"/>
<TextEquiv>
<Unicode/>
</TextEquiv>
</TextLine>
</TextRegion>
这应该是你想要的。
如果要向 Unicode
元素添加值,请让您的模板与 Unicode
元素相匹配:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Unicode">
<xsl:copy>
<xsl:if test="../../@id='eSc_line_b74d9f71'">something else</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
或者简单地说:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="TextLine[@id='eSc_line_b74d9f71']/TextEquiv/Unicode">
<xsl:copy>something else</xsl:copy>
</xsl:template>
</xsl:stylesheet>
另请注意,属性没有子项。并且文本节点不能为空。这些都是您的模板永远不会匹配任何内容的充分理由。
所以,mi 问题看起来很简单,但我被卡住了。我想根据 id 属性在 xml 中填充文本元素,我的 xml 是一个如下所示的 PageXML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PcGts xmlns="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15 http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15/pagecontent.xsd">
<Metadata>
<Creator>myself</Creator>
<Created>2021-07-03T09:37:54.369908+00:00</Created>
<LastChange>2021-07-03T09:37:54.369944+00:00</LastChange>
</Metadata>
<Page imageFilename="05.tif" imageWidth="3243" imageHeight="4077">
<TextRegion id="eSc_dummyblock_">
<TextLine id="eSc_line_b74d9f71" >
<Coords points="1376,108 1390,67 1492,78 1492,166 1431,149 1407,166 1390,149 1376,156"/>
<Baseline points="1380,112 1499,112"/>
<TextEquiv>
<Unicode></Unicode>
</TextEquiv>
</TextLine>
<TextLine id="eSc_line_5aceacfb" >
<Coords points="2882,173 2882,142 2947,125 2947,292 2920,288 2882,309"/>
<Baseline points="2886,176 2954,176"/>
<TextEquiv>
<Unicode>toto</Unicode>
</TextEquiv>
</TextLine>
</TextRegion>
</Page>
</PcGts>
我只想传递一个 xslt 模板,以便根据 TextLine id 属性用不同的值填充每个 Unicode 元素。像这样的东西必须工作,但是,没有任何反应。
import lxml.etree as ET
dom = ET.parse(filename)
xslt_root = etree.XML(
'''<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@id[. = 'eSc_line_b74d9f71']/*/Unicode/text()[. = '']">something else</xsl:template>
</xsl:stylesheet>''')
transform = ET.XSLT(xslt_root)
newdom = transform(dom)
期望的输出:
<?xml version="1.0" encoding="UTF-8"?>
<TextRegion id="eSc_dummyblock_">
<TextLine id="eSc_line_b74d9f71">
<Coords points="1376,108 1390,67 1492,78 1492,166 1431,149 1407,166 1390,149 1376,156"/>
<Baseline points="1380,112 1499,112"/>
<TextEquiv>
<Unicode>something else</Unicode>
</TextEquiv>
</TextLine>
<TextLine id="eSc_line_5aceacfb">
<Coords points="2882,173 2882,142 2947,125 2947,292 2920,288 2882,309"/>
<Baseline points="2886,176 2954,176"/>
<TextEquiv>
<Unicode/>
</TextEquiv>
</TextLine>
</TextRegion>
我会感谢你的帮助
----解决方案---
正如@michael.hor257k 所建议的那样,解决方案是在 xslt 样式表中声明相同的名称空间:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:met="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15"
exclude-result-prefixes="met">
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="met:TextLine[@id='eSc_line_b74d9f71']/met:TextEquiv/met:Unicode">
<xsl:copy>something else</xsl:copy>
</xsl:template>
</xsl:stylesheet>
换行怎么样
<xsl:template match="@id[. = 'eSc_line_b74d9f71']/*/Unicode/text()[. = '']">something else</xsl:template>
到
<xsl:template match="*[@id = 'eSc_line_b74d9f71']/TextEquiv/Unicode"><Unicode>something else</Unicode></xsl:template>
或者更通用的版本
<xsl:template match="*[@id = 'eSc_line_b74d9f71']/TextEquiv/Unicode"><xsl:copy>something else</xsl:copy></xsl:template>
根据您的输入,这将为您提供输出
<?xml version="1.0" encoding="UTF-8"?>
<TextRegion id="eSc_dummyblock_">
<TextLine id="eSc_line_b74d9f71">
<Coords points="1376,108 1390,67 1492,78 1492,166 1431,149 1407,166 1390,149 1376,156"/>
<Baseline points="1380,112 1499,112"/>
<TextEquiv>
<Unicode>something else</Unicode>
</TextEquiv>
</TextLine>
<TextLine id="eSc_line_5aceacfb">
<Coords points="2882,173 2882,142 2947,125 2947,292 2920,288 2882,309"/>
<Baseline points="2886,176 2954,176"/>
<TextEquiv>
<Unicode/>
</TextEquiv>
</TextLine>
</TextRegion>
这应该是你想要的。
如果要向 Unicode
元素添加值,请让您的模板与 Unicode
元素相匹配:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Unicode">
<xsl:copy>
<xsl:if test="../../@id='eSc_line_b74d9f71'">something else</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
或者简单地说:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="TextLine[@id='eSc_line_b74d9f71']/TextEquiv/Unicode">
<xsl:copy>something else</xsl:copy>
</xsl:template>
</xsl:stylesheet>
另请注意,属性没有子项。并且文本节点不能为空。这些都是您的模板永远不会匹配任何内容的充分理由。